diff options
158 files changed, 1849 insertions, 930 deletions
diff --git a/.qmake.conf b/.qmake.conf index 31a134c4cc..db74e7164b 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,4 +1,4 @@ load(qt_build_config) CONFIG += warning_clean -MODULE_VERSION = 5.11.0 +MODULE_VERSION = 5.11.1 diff --git a/examples/qml/networkaccessmanagerfactory/main.cpp b/examples/qml/networkaccessmanagerfactory/main.cpp index 95dfb5990d..a0fddf50c6 100644 --- a/examples/qml/networkaccessmanagerfactory/main.cpp +++ b/examples/qml/networkaccessmanagerfactory/main.cpp @@ -133,7 +133,8 @@ int main(int argc, char ** argv) source = QUrl::fromLocalFile(parser.positionalArguments().first()); QQuickView view; - view.engine()->setNetworkAccessManagerFactory(new MyNetworkAccessManagerFactory); + MyNetworkAccessManagerFactory networkManagerFactory; + view.engine()->setNetworkAccessManagerFactory(&networkManagerFactory); view.setSource(source); view.show(); diff --git a/src/3rdparty/masm/assembler/ARM64Assembler.h b/src/3rdparty/masm/assembler/ARM64Assembler.h index 008f03bccf..1787e921e8 100644 --- a/src/3rdparty/masm/assembler/ARM64Assembler.h +++ b/src/3rdparty/masm/assembler/ARM64Assembler.h @@ -39,6 +39,10 @@ #include <libkern/OSCacheControl.h> #endif +#if OS(INTEGRITY) +#include <INTEGRITY.h> +#endif + #define CHECK_DATASIZE_OF(datasize) ASSERT(datasize == 32 || datasize == 64) #define DATASIZE_OF(datasize) ((datasize == 64) ? Datasize_64 : Datasize_32) #define MEMOPSIZE_OF(datasize) ((datasize == 8 || datasize == 128) ? MemOpSize_8_or_128 : (datasize == 16) ? MemOpSize_16 : (datasize == 32) ? MemOpSize_32 : MemOpSize_64) @@ -3039,6 +3043,8 @@ public: UNUSED_PARAM(code); UNUSED_PARAM(size); #endif +#elif OS(INTEGRITY) + ManageCaches((Address)code, size, ACCESS_DST_COHERENT); #else #error "The cacheFlush support is missing on this platform." #endif diff --git a/src/3rdparty/masm/assembler/AbstractMacroAssembler.h b/src/3rdparty/masm/assembler/AbstractMacroAssembler.h index 6fac27fdf1..1076384900 100644 --- a/src/3rdparty/masm/assembler/AbstractMacroAssembler.h +++ b/src/3rdparty/masm/assembler/AbstractMacroAssembler.h @@ -327,7 +327,13 @@ public: template<class TemplateAssemblerType> friend class AbstractMacroAssembler; friend struct DFG::OSRExit; + +#if CPU(ARM_THUMB2) || CPU(ARM64) || defined(V4_BOOTSTRAP) + using Jump = typename AssemblerType::template Jump<Label>; + friend Jump; +#else friend class Jump; +#endif friend class JumpReplacementWatchpoint; friend class MacroAssemblerCodeRef; template <typename, template <typename> class> friend class LinkBufferBase; diff --git a/src/3rdparty/masm/assembler/MacroAssemblerARM64.h b/src/3rdparty/masm/assembler/MacroAssemblerARM64.h index 1f94eb9032..ba0d7e93f8 100644 --- a/src/3rdparty/masm/assembler/MacroAssemblerARM64.h +++ b/src/3rdparty/masm/assembler/MacroAssemblerARM64.h @@ -3101,40 +3101,22 @@ private: } template<int datasize> - ALWAYS_INLINE void loadUnsignedImmediate(RegisterID rt, RegisterID rn, unsigned pimm) - { - m_assembler.ldr<datasize>(rt, rn, pimm); - } + void loadUnsignedImmediate(RegisterID rt, RegisterID rn, unsigned pimm); template<int datasize> - ALWAYS_INLINE void loadUnscaledImmediate(RegisterID rt, RegisterID rn, int simm) - { - m_assembler.ldur<datasize>(rt, rn, simm); - } + void loadUnscaledImmediate(RegisterID rt, RegisterID rn, int simm); template<int datasize> - ALWAYS_INLINE void loadSignedAddressedByUnsignedImmediate(RegisterID rt, RegisterID rn, unsigned pimm) - { - loadUnsignedImmediate<datasize>(rt, rn, pimm); - } + void loadSignedAddressedByUnsignedImmediate(RegisterID rt, RegisterID rn, unsigned pimm); template<int datasize> - ALWAYS_INLINE void loadSignedAddressedByUnscaledImmediate(RegisterID rt, RegisterID rn, int simm) - { - loadUnscaledImmediate<datasize>(rt, rn, simm); - } + void loadSignedAddressedByUnscaledImmediate(RegisterID rt, RegisterID rn, int simm); template<int datasize> - ALWAYS_INLINE void storeUnsignedImmediate(RegisterID rt, RegisterID rn, unsigned pimm) - { - m_assembler.str<datasize>(rt, rn, pimm); - } + void storeUnsignedImmediate(RegisterID rt, RegisterID rn, unsigned pimm); template<int datasize> - ALWAYS_INLINE void storeUnscaledImmediate(RegisterID rt, RegisterID rn, int simm) - { - m_assembler.stur<datasize>(rt, rn, simm); - } + void storeUnscaledImmediate(RegisterID rt, RegisterID rn, int simm); void moveWithFixedWidth(TrustedImm32 imm, RegisterID dest) { @@ -3299,74 +3281,19 @@ private: } template<int datasize> - ALWAYS_INLINE bool tryLoadWithOffset(RegisterID rt, RegisterID rn, int32_t offset) - { - if (ARM64Assembler::canEncodeSImmOffset(offset)) { - loadUnscaledImmediate<datasize>(rt, rn, offset); - return true; - } - if (ARM64Assembler::canEncodePImmOffset<datasize>(offset)) { - loadUnsignedImmediate<datasize>(rt, rn, static_cast<unsigned>(offset)); - return true; - } - return false; - } + bool tryLoadWithOffset(RegisterID rt, RegisterID rn, int32_t offset); template<int datasize> - ALWAYS_INLINE bool tryLoadSignedWithOffset(RegisterID rt, RegisterID rn, int32_t offset) - { - if (ARM64Assembler::canEncodeSImmOffset(offset)) { - loadSignedAddressedByUnscaledImmediate<datasize>(rt, rn, offset); - return true; - } - if (ARM64Assembler::canEncodePImmOffset<datasize>(offset)) { - loadSignedAddressedByUnsignedImmediate<datasize>(rt, rn, static_cast<unsigned>(offset)); - return true; - } - return false; - } + bool tryLoadSignedWithOffset(RegisterID rt, RegisterID rn, int32_t offset); template<int datasize> - ALWAYS_INLINE bool tryLoadWithOffset(FPRegisterID rt, RegisterID rn, int32_t offset) - { - if (ARM64Assembler::canEncodeSImmOffset(offset)) { - m_assembler.ldur<datasize>(rt, rn, offset); - return true; - } - if (ARM64Assembler::canEncodePImmOffset<datasize>(offset)) { - m_assembler.ldr<datasize>(rt, rn, static_cast<unsigned>(offset)); - return true; - } - return false; - } + bool tryLoadWithOffset(FPRegisterID rt, RegisterID rn, int32_t offset); template<int datasize> - ALWAYS_INLINE bool tryStoreWithOffset(RegisterID rt, RegisterID rn, int32_t offset) - { - if (ARM64Assembler::canEncodeSImmOffset(offset)) { - storeUnscaledImmediate<datasize>(rt, rn, offset); - return true; - } - if (ARM64Assembler::canEncodePImmOffset<datasize>(offset)) { - storeUnsignedImmediate<datasize>(rt, rn, static_cast<unsigned>(offset)); - return true; - } - return false; - } + bool tryStoreWithOffset(RegisterID rt, RegisterID rn, int32_t offset); template<int datasize> - ALWAYS_INLINE bool tryStoreWithOffset(FPRegisterID rt, RegisterID rn, int32_t offset) - { - if (ARM64Assembler::canEncodeSImmOffset(offset)) { - m_assembler.stur<datasize>(rt, rn, offset); - return true; - } - if (ARM64Assembler::canEncodePImmOffset<datasize>(offset)) { - m_assembler.str<datasize>(rt, rn, static_cast<unsigned>(offset)); - return true; - } - return false; - } + bool tryStoreWithOffset(FPRegisterID rt, RegisterID rn, int32_t offset); Jump jumpAfterFloatingPointCompare(DoubleCondition cond) { @@ -3413,6 +3340,43 @@ private: bool m_allowScratchRegister = true; }; +template<int datasize> +ALWAYS_INLINE void MacroAssemblerARM64::loadUnsignedImmediate(RegisterID rt, RegisterID rn, unsigned pimm) +{ + m_assembler.ldr<datasize>(rt, rn, pimm); +} + +template<int datasize> +ALWAYS_INLINE void MacroAssemblerARM64::loadUnscaledImmediate(RegisterID rt, RegisterID rn, int simm) +{ + m_assembler.ldur<datasize>(rt, rn, simm); +} + +template<int datasize> +ALWAYS_INLINE void MacroAssemblerARM64::loadSignedAddressedByUnsignedImmediate(RegisterID rt, RegisterID rn, unsigned pimm) +{ + loadUnsignedImmediate<datasize>(rt, rn, pimm); +} + +template<int datasize> +ALWAYS_INLINE void MacroAssemblerARM64::loadSignedAddressedByUnscaledImmediate(RegisterID rt, RegisterID rn, int simm) +{ + loadUnscaledImmediate<datasize>(rt, rn, simm); +} + +template<int datasize> +ALWAYS_INLINE void MacroAssemblerARM64::storeUnsignedImmediate(RegisterID rt, RegisterID rn, unsigned pimm) +{ + m_assembler.str<datasize>(rt, rn, pimm); +} + +template<int datasize> +ALWAYS_INLINE void MacroAssemblerARM64::storeUnscaledImmediate(RegisterID rt, RegisterID rn, int simm) +{ + m_assembler.stur<datasize>(rt, rn, simm); +} + + // Extend the {load,store}{Unsigned,Unscaled}Immediate templated general register methods to cover all load/store sizes template<> ALWAYS_INLINE void MacroAssemblerARM64::loadUnsignedImmediate<8>(RegisterID rt, RegisterID rn, unsigned pimm) @@ -3486,6 +3450,77 @@ ALWAYS_INLINE void MacroAssemblerARM64::storeUnscaledImmediate<16>(RegisterID rt m_assembler.sturh(rt, rn, simm); } +template<int datasize> +ALWAYS_INLINE bool MacroAssemblerARM64::tryLoadSignedWithOffset(RegisterID rt, RegisterID rn, int32_t offset) +{ + if (ARM64Assembler::canEncodeSImmOffset(offset)) { + loadSignedAddressedByUnscaledImmediate<datasize>(rt, rn, offset); + return true; + } + if (ARM64Assembler::canEncodePImmOffset<datasize>(offset)) { + loadSignedAddressedByUnsignedImmediate<datasize>(rt, rn, static_cast<unsigned>(offset)); + return true; + } + return false; +} + +template<int datasize> +ALWAYS_INLINE bool MacroAssemblerARM64::tryStoreWithOffset(RegisterID rt, RegisterID rn, int32_t offset) +{ + if (ARM64Assembler::canEncodeSImmOffset(offset)) { + storeUnscaledImmediate<datasize>(rt, rn, offset); + return true; + } + if (ARM64Assembler::canEncodePImmOffset<datasize>(offset)) { + storeUnsignedImmediate<datasize>(rt, rn, static_cast<unsigned>(offset)); + return true; + } + return false; +} + +template<int datasize> +ALWAYS_INLINE bool MacroAssemblerARM64::tryStoreWithOffset(FPRegisterID rt, RegisterID rn, int32_t offset) +{ + if (ARM64Assembler::canEncodeSImmOffset(offset)) { + m_assembler.stur<datasize>(rt, rn, offset); + return true; + } + if (ARM64Assembler::canEncodePImmOffset<datasize>(offset)) { + m_assembler.str<datasize>(rt, rn, static_cast<unsigned>(offset)); + return true; + } + return false; +} + + +template<int datasize> +ALWAYS_INLINE bool MacroAssemblerARM64::tryLoadWithOffset(RegisterID rt, RegisterID rn, int32_t offset) +{ + if (ARM64Assembler::canEncodeSImmOffset(offset)) { + loadUnscaledImmediate<datasize>(rt, rn, offset); + return true; + } + if (ARM64Assembler::canEncodePImmOffset<datasize>(offset)) { + loadUnsignedImmediate<datasize>(rt, rn, static_cast<unsigned>(offset)); + return true; + } + return false; +} + +template<int datasize> +ALWAYS_INLINE bool MacroAssemblerARM64::tryLoadWithOffset(FPRegisterID rt, RegisterID rn, int32_t offset) + { + if (ARM64Assembler::canEncodeSImmOffset(offset)) { + m_assembler.ldur<datasize>(rt, rn, offset); + return true; + } + if (ARM64Assembler::canEncodePImmOffset<datasize>(offset)) { + m_assembler.ldr<datasize>(rt, rn, static_cast<unsigned>(offset)); + return true; + } + return false; + } + } // namespace JSC #endif // ENABLE(ASSEMBLER) diff --git a/src/3rdparty/masm/stubs/ExecutableAllocator.h b/src/3rdparty/masm/stubs/ExecutableAllocator.h index 3b84b5c986..1ab28588fb 100644 --- a/src/3rdparty/masm/stubs/ExecutableAllocator.h +++ b/src/3rdparty/masm/stubs/ExecutableAllocator.h @@ -45,6 +45,10 @@ #include <private/qv4executableallocator_p.h> +#if OS(INTEGRITY) +#include "OSAllocator.h" +#endif + #if OS(WINDOWS) #include <windows.h> #else @@ -118,6 +122,8 @@ struct ExecutableAllocator { Q_UNREACHABLE(); } # endif +# elif OS(INTEGRITY) + OSAllocator::setMemoryAttributes(addr, /*writable*/ true, /*executable*/ false); # else int mode = PROT_READ | PROT_WRITE; if (mprotect(addr, size, mode) != 0) { @@ -152,6 +158,8 @@ struct ExecutableAllocator { Q_UNREACHABLE(); } # endif +# elif OS(INTEGRITY) + OSAllocator::setMemoryAttributes(addr, /*writable*/ false, /*executable*/ true); # else int mode = PROT_READ | PROT_EXEC; if (mprotect(addr, size, mode) != 0) { diff --git a/src/3rdparty/masm/wtf/OSAllocator.h b/src/3rdparty/masm/wtf/OSAllocator.h index 933b3cda0a..366dd73993 100644 --- a/src/3rdparty/masm/wtf/OSAllocator.h +++ b/src/3rdparty/masm/wtf/OSAllocator.h @@ -73,6 +73,10 @@ public: static T* reallocateCommitted(T*, size_t oldSize, size_t newSize, Usage = UnknownUsage, bool writable = true, bool executable = false); static bool canAllocateExecutableMemory(); + +#if defined(Q_OS_INTEGRITY) + static void setMemoryAttributes(void* addr, bool writable, bool executable); +#endif }; inline void* OSAllocator::reserveAndCommit(size_t reserveSize, size_t commitSize, Usage usage, bool writable, bool executable) diff --git a/src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp b/src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp index 451ca147d1..7addf9e5c2 100644 --- a/src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp +++ b/src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp @@ -123,6 +123,12 @@ Error setAttributes(MemoryRegion mr, bool writable, bool executable) return SetMemoryRegionAttributes(mr, attributes); } +void OSAllocator::setMemoryAttributes(void* addr, bool writable, bool executable) +{ + const MRPair* pair = memoryRegionsContainer.getMRPair((Address)addr); + CheckSuccess(setAttributes(pair->vmr, writable, executable)); +} + void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable) { MemoryRegion VMR; @@ -229,4 +235,10 @@ void OSAllocator::releaseDecommitted(void* address, size_t bytes) memoryRegionsContainer.deleteMRPair(pair); } } + +bool OSAllocator::canAllocateExecutableMemory() +{ + return true; +} + } // namespace WTF diff --git a/src/3rdparty/masm/wtf/Platform.h b/src/3rdparty/masm/wtf/Platform.h index a81ef4589a..edb688923b 100644 --- a/src/3rdparty/masm/wtf/Platform.h +++ b/src/3rdparty/masm/wtf/Platform.h @@ -172,6 +172,11 @@ #define WTF_CPU_ARM64 1 #endif +/* CPU(ARM64) - INTEGRITY */ +#if (defined(__ARM64__)) +#define WTF_CPU_ARM64 1 +#endif + /* CPU(ARM) - ARM, any version*/ #define WTF_ARM_ARCH_AT_LEAST(N) (CPU(ARM) && WTF_ARM_ARCH_VERSION >= N) diff --git a/src/imports/imports.pro b/src/imports/imports.pro index 5d7e434884..e188602277 100644 --- a/src/imports/imports.pro +++ b/src/imports/imports.pro @@ -17,14 +17,14 @@ qtHaveModule(quick) { handlers \ layouts \ qtquick2 \ - window \ - testlib + window + qtHaveModule(testlib): SUBDIRS += testlib qtConfig(systemsemaphore): SUBDIRS += sharedimage qtConfig(quick-particles): \ SUBDIRS += particles - SUBDIRS += shapes + qtConfig(quick-path): SUBDIRS += shapes } qtHaveModule(xmlpatterns) : SUBDIRS += xmllistmodel diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp index d2fb78d72a..abd7793a74 100644 --- a/src/particles/qquickimageparticle.cpp +++ b/src/particles/qquickimageparticle.cpp @@ -1321,7 +1321,7 @@ void QQuickImageParticle::finishBuildParticleNodes(QSGNode** node) m_material = SpriteMaterial::createMaterial(); if (imageLoaded) getState<ImageMaterialData>(m_material)->texture = QSGPlainTexture::fromImage(image); - getState<ImageMaterialData>(m_material)->animSheetSize = QSizeF(image.size()); + getState<ImageMaterialData>(m_material)->animSheetSize = QSizeF(image.size() / image.devicePixelRatioF()); if (m_spriteEngine) m_spriteEngine->setCount(m_count); Q_FALLTHROUGH(); diff --git a/src/plugins/qmltooling/packetprotocol/packetprotocol.pro b/src/plugins/qmltooling/packetprotocol/packetprotocol.pro index 990d3169ad..a188b87a81 100644 --- a/src/plugins/qmltooling/packetprotocol/packetprotocol.pro +++ b/src/plugins/qmltooling/packetprotocol/packetprotocol.pro @@ -1,11 +1,11 @@ TARGET = QtPacketProtocol -QT = core-private qml-private +QT = core-private CONFIG += static internal_module HEADERS = \ qpacketprotocol_p.h \ qpacket_p.h \ - qqmldebugpacket_p.h + qversionedpacket_p.h SOURCES = \ qpacketprotocol.cpp \ diff --git a/src/plugins/qmltooling/packetprotocol/qqmldebugpacket_p.h b/src/plugins/qmltooling/packetprotocol/qversionedpacket_p.h index 9a0f8cd82d..635072adbc 100644 --- a/src/plugins/qmltooling/packetprotocol/qqmldebugpacket_p.h +++ b/src/plugins/qmltooling/packetprotocol/qversionedpacket_p.h @@ -37,14 +37,11 @@ ** ****************************************************************************/ -#ifndef QQMLDEBUGPACKET_P_H -#define QQMLDEBUGPACKET_P_H +#ifndef QVERSIONEDPACKET_P_H +#define QVERSIONEDPACKET_P_H #include "qpacket_p.h" -#include <QtCore/qbuffer.h> -#include <QtQml/private/qqmldebugconnector_p.h> - // // W A R N I N G // ------------- @@ -58,14 +55,15 @@ QT_BEGIN_NAMESPACE -// QPacket with a fixed data stream version, centrally set by QQmlDebugServer -class QQmlDebugPacket : public QPacket +// QPacket with a fixed data stream version, centrally set by some Connector +template<class Connector> +class QVersionedPacket : public QPacket { public: - QQmlDebugPacket() : QPacket(QQmlDebugConnector::dataStreamVersion()) {} - QQmlDebugPacket(const QByteArray &ba) : QPacket(QQmlDebugConnector::dataStreamVersion(), ba) {} + QVersionedPacket(const QByteArray &ba) : QPacket(Connector::dataStreamVersion(), ba) {} + QVersionedPacket() : QPacket(Connector::dataStreamVersion()) {} }; QT_END_NAMESPACE -#endif // QQMLDEBUGPACKET_P_H +#endif // QVERSIONEDPACKET_P_H diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp index 236109d041..17bae6d695 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp @@ -55,11 +55,19 @@ #include <QtCore/qdebug.h> #include <QtCore/qmetaobject.h> #include <QtCore/qfileinfo.h> +#include <QtCore/qjsonvalue.h> +#include <QtCore/qjsonobject.h> +#include <QtCore/qjsonarray.h> +#include <QtCore/qjsondocument.h> + #include <private/qmetaobject_p.h> -#include <private/qqmldebugpacket_p.h> +#include <private/qqmldebugconnector_p.h> +#include <private/qversionedpacket_p.h> QT_BEGIN_NAMESPACE +using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>; + QQmlEngineDebugServiceImpl::QQmlEngineDebugServiceImpl(QObject *parent) : QQmlEngineDebugService(2, parent), m_watch(new QQmlWatcher(this)), m_statesDelegate(nullptr) { @@ -208,34 +216,40 @@ QVariant QQmlEngineDebugServiceImpl::valueContents(QVariant value) const return contents; } - if (QQmlValueTypeFactory::isValueType(userType)) { - switch (userType) { - case QMetaType::QRect: - case QMetaType::QRectF: - case QMetaType::QPoint: - case QMetaType::QPointF: - case QMetaType::QSize: - case QMetaType::QSizeF: - case QMetaType::QFont: - // Don't call the toString() method on those. The stream operators are better. - return value; - default: - break; - } - - const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(userType); - if (mo) { - int toStringIndex = mo->indexOfMethod("toString()"); - if (toStringIndex != -1) { - QMetaMethod mm = mo->method(toStringIndex); - QString s; - if (mm.invokeOnGadget(value.data(), Q_RETURN_ARG(QString, s))) - return s; + switch (userType) { + case QMetaType::QRect: + case QMetaType::QRectF: + case QMetaType::QPoint: + case QMetaType::QPointF: + case QMetaType::QSize: + case QMetaType::QSizeF: + case QMetaType::QFont: + // Don't call the toString() method on those. The stream operators are better. + return value; + case QMetaType::QJsonValue: + return value.toJsonValue().toVariant(); + case QMetaType::QJsonObject: + return value.toJsonObject().toVariantMap(); + case QMetaType::QJsonArray: + return value.toJsonArray().toVariantList(); + case QMetaType::QJsonDocument: + return value.toJsonDocument().toVariant(); + default: + if (QQmlValueTypeFactory::isValueType(userType)) { + const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(userType); + if (mo) { + int toStringIndex = mo->indexOfMethod("toString()"); + if (toStringIndex != -1) { + QMetaMethod mm = mo->method(toStringIndex); + QString s; + if (mm.invokeOnGadget(value.data(), Q_RETURN_ARG(QString, s))) + return s; + } } - } - // We expect all QML value types to either have a toString() method or stream operators - return value; + // We expect all QML value types to either have a toString() method or stream operators + return value; + } } if (QQmlMetaType::isQObject(userType)) { diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp index c86f3d1803..95e6d5704c 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp @@ -72,16 +72,12 @@ QV4::Heap::ExecutionContext *QV4DataCollector::findContext(int frame) return f ? f->context()->d() : nullptr; } -QV4::Heap::CallContext *QV4DataCollector::findScope(QV4::Heap::ExecutionContext *ctx, int scope) +QV4::Heap::ExecutionContext *QV4DataCollector::findScope(QV4::Heap::ExecutionContext *ctx, int scope) { - if (!ctx) - return nullptr; - for (; scope > 0 && ctx; --scope) ctx = ctx->outer; - return (ctx && ctx->type == QV4::Heap::ExecutionContext::Type_CallContext) ? - static_cast<QV4::Heap::CallContext *>(ctx) : nullptr; + return ctx; } QVector<QV4::Heap::ExecutionContext::ContextType> QV4DataCollector::getScopeTypes(int frame) @@ -108,6 +104,7 @@ int QV4DataCollector::encodeScopeType(QV4::Heap::ExecutionContext::ContextType s case QV4::Heap::ExecutionContext::Type_CallContext: return 1; case QV4::Heap::ExecutionContext::Type_QmlContext: + return 3; default: return -1; } @@ -259,31 +256,32 @@ bool QV4DataCollector::isValidRef(QV4DataCollector::Ref ref) const bool QV4DataCollector::collectScope(QJsonObject *dict, int frameNr, int scopeNr) { - QStringList names; - QV4::Scope scope(engine()); - QV4::Scoped<QV4::CallContext> ctxt(scope, findScope(findContext(frameNr), scopeNr)); + QV4::Scoped<QV4::ExecutionContext> ctxt(scope, findScope(findContext(frameNr), scopeNr)); if (!ctxt) return false; - Refs collectedRefs; - QV4::ScopedValue v(scope); - QV4::InternalClass *ic = ctxt->internalClass(); - for (uint i = 0; i < ic->size; ++i) { - QString name = ic->nameMap[i]->string; - names.append(name); - v = ctxt->d()->locals[i]; - collectedRefs.append(collect(v)); - } - QV4::ScopedObject scopeObject(scope, engine()->newObject()); + if (ctxt->d()->type == QV4::Heap::ExecutionContext::Type_CallContext) { + QStringList names; + Refs collectedRefs; + + QV4::ScopedValue v(scope); + QV4::InternalClass *ic = ctxt->internalClass(); + for (uint i = 0; i < ic->size; ++i) { + QString name = ic->nameMap[i]->string; + names.append(name); + v = static_cast<QV4::Heap::CallContext *>(ctxt->d())->locals[i]; + collectedRefs.append(collect(v)); + } - Q_ASSERT(names.size() == collectedRefs.size()); - QV4::ScopedString propName(scope); - for (int i = 0, ei = collectedRefs.size(); i != ei; ++i) { - propName = engine()->newString(names.at(i)); - scopeObject->put(propName, QV4::Value::fromReturnedValue(getValue(collectedRefs.at(i)))); + Q_ASSERT(names.size() == collectedRefs.size()); + QV4::ScopedString propName(scope); + for (int i = 0, ei = collectedRefs.size(); i != ei; ++i) { + propName = engine()->newString(names.at(i)); + scopeObject->put(propName, (v = getValue(collectedRefs.at(i)))); + } } Ref scopeObjectRef = addRef(scopeObject); diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h index 87be009de5..5494e10e9a 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h @@ -58,7 +58,7 @@ public: typedef uint Ref; typedef QVector<uint> Refs; - static QV4::Heap::CallContext *findScope(QV4::Heap::ExecutionContext *ctxt, int scope); + static QV4::Heap::ExecutionContext *findScope(QV4::Heap::ExecutionContext *ctxt, int scope); static int encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType); QVector<QV4::Heap::ExecutionContext::ContextType> getScopeTypes(int frame); diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp index 61209e08cb..32de8e9027 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp @@ -45,7 +45,7 @@ #include <private/qv4function_p.h> #include <private/qqmldebugconnector_p.h> #include <private/qv8engine_p.h> -#include <private/qqmldebugpacket_p.h> +#include <private/qversionedpacket_p.h> #include <QtCore/QJsonArray> #include <QtCore/QJsonDocument> @@ -70,6 +70,8 @@ QT_BEGIN_NAMESPACE class V8CommandHandler; class UnknownV8CommandHandler; +using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>; + int QV4DebugServiceImpl::sequence = 0; class V8CommandHandler diff --git a/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp index 7ce83daed6..bac4e01df1 100644 --- a/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp +++ b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp @@ -44,7 +44,8 @@ #include <private/qqmldebugserviceinterfaces_p.h> #include <private/qabstractanimation_p.h> #include <private/qqmlcomponent_p.h> -#include <private/qqmldebugpacket_p.h> +#include <private/qqmldebugconnector_p.h> +#include <private/qversionedpacket_p.h> #include <QtGui/qwindow.h> @@ -63,6 +64,8 @@ QT_BEGIN_NAMESPACE +using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>; + const char REQUEST[] = "request"; const char RESPONSE[] = "response"; const char EVENT[] = "event"; diff --git a/src/plugins/qmltooling/qmldbg_messages/qdebugmessageservice.cpp b/src/plugins/qmltooling/qmldbg_messages/qdebugmessageservice.cpp index 2bf9210b37..4f6cb9364d 100644 --- a/src/plugins/qmltooling/qmldbg_messages/qdebugmessageservice.cpp +++ b/src/plugins/qmltooling/qmldbg_messages/qdebugmessageservice.cpp @@ -40,10 +40,12 @@ #include "qdebugmessageservice.h" #include <private/qqmldebugconnector_p.h> -#include <private/qqmldebugpacket_p.h> +#include <private/qversionedpacket_p.h> QT_BEGIN_NAMESPACE +using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>; + void DebugMessageHandler(QtMsgType type, const QMessageLogContext &ctxt, const QString &buf) { diff --git a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp index 93ac875e2d..bf73440a39 100644 --- a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp +++ b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp @@ -40,7 +40,7 @@ #include "qqmlnativedebugconnector.h" #include <private/qhooks_p.h> -#include <private/qqmldebugpacket_p.h> +#include <private/qversionedpacket_p.h> #include <QtQml/qjsengine.h> #include <QtCore/qdebug.h> diff --git a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp index e17fe92983..b19115aa60 100644 --- a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp @@ -49,7 +49,7 @@ #include <private/qv4objectiterator_p.h> #include <private/qv4identifier_p.h> #include <private/qv4runtime_p.h> -#include <private/qqmldebugpacket_p.h> +#include <private/qversionedpacket_p.h> #include <private/qqmldebugserviceinterfaces_p.h> #include <QtQml/qjsengine.h> @@ -65,6 +65,8 @@ QT_BEGIN_NAMESPACE +using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>; + class BreakPoint { public: diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp index 4eedb4bd51..f76add448f 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp @@ -38,11 +38,14 @@ ****************************************************************************/ #include "qqmlenginecontrolservice.h" -#include <private/qqmldebugpacket_p.h> +#include <private/qqmldebugconnector_p.h> +#include <private/qversionedpacket_p.h> #include <QJSEngine> QT_BEGIN_NAMESPACE +using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>; + QQmlEngineControlServiceImpl::QQmlEngineControlServiceImpl(QObject *parent) : QQmlEngineControlService(1, parent) { diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp index 5ff1b1f97e..19104927f2 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp @@ -38,8 +38,8 @@ ****************************************************************************/ #include "qqmlprofileradapter.h" +#include "qqmlprofilerservice.h" -#include <private/qqmldebugpacket_p.h> #include <private/qqmldebugserviceinterfaces_p.h> QT_BEGIN_NAMESPACE diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp index 7014249c83..21a5663f59 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp @@ -43,7 +43,6 @@ #include "qqmlprofilerservicefactory.h" #include <private/qjsengine_p.h> -#include <private/qqmldebugpacket_p.h> #include <private/qqmldebugpluginmanager_p.h> #include <QtCore/qurl.h> diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h index a8c3047421..2b92a478c1 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h @@ -56,6 +56,8 @@ #include <private/qqmlprofilerdefinitions_p.h> #include <private/qqmlabstractprofileradapter_p.h> #include <private/qqmlboundsignal_p.h> +#include <private/qqmldebugconnector_p.h> +#include <private/qversionedpacket_p.h> #include <QtCore/qelapsedtimer.h> #include <QtCore/qmetaobject.h> @@ -70,6 +72,7 @@ QT_BEGIN_NAMESPACE class QUrl; +using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>; class QQmlProfilerServiceImpl : public QQmlConfigurableDebugService<QQmlProfilerService>, diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h index 7ac378acd9..2211c82fc5 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h +++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h @@ -51,9 +51,10 @@ // We mean it. // +#include "qqmlprofilerservice.h" + #include <private/qv4profiling_p.h> #include <private/qqmlabstractprofileradapter_p.h> -#include <private/qqmldebugpacket_p.h> #include <QStack> #include <QList> diff --git a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp index a05d11664d..2c152e4cd5 100644 --- a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp +++ b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp @@ -40,12 +40,15 @@ #include "qquickprofileradapter.h" #include <QCoreApplication> -#include <private/qqmldebugpacket_p.h> +#include <private/qqmldebugconnector_p.h> +#include <private/qversionedpacket_p.h> #include <private/qqmldebugserviceinterfaces_p.h> #include <private/qquickprofiler_p.h> QT_BEGIN_NAMESPACE +using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>; + QQuickProfilerAdapter::QQuickProfilerAdapter(QObject *parent) : QQmlAbstractProfilerAdapter(parent), next(0) { diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp index 1814e28b83..c1e86f0b3c 100644 --- a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp +++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp @@ -47,7 +47,7 @@ #include <private/qqmldebugpluginmanager_p.h> #include <private/qqmldebugserviceinterfaces_p.h> #include <private/qpacketprotocol_p.h> -#include <private/qqmldebugpacket_p.h> +#include <private/qversionedpacket_p.h> #include <QtCore/QAtomicInt> #include <QtCore/QDir> @@ -83,6 +83,7 @@ QT_BEGIN_NAMESPACE Q_QML_DEBUG_PLUGIN_LOADER(QQmlDebugServerConnection) const int protocolVersion = 1; +using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>; class QQmlDebugServerImpl; class QQmlDebugServerThread : public QThread diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 4a1b27d7aa..8a1b3744ee 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -322,16 +322,16 @@ Document::Document(bool debugMode) { } -ScriptDirectivesCollector::ScriptDirectivesCollector(QQmlJS::Engine *engine, QV4::Compiler::JSUnitGenerator *unitGenerator) - : engine(engine) - , jsGenerator(unitGenerator) - , hasPragmaLibrary(false) +ScriptDirectivesCollector::ScriptDirectivesCollector(Document *doc) + : document(doc) + , engine(&doc->jsParserEngine) + , jsGenerator(&doc->jsGenerator) { } void ScriptDirectivesCollector::pragmaLibrary() { - hasPragmaLibrary = true; + document->jsModule.unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary; } void ScriptDirectivesCollector::importFile(const QString &jsfile, const QString &module, int lineNumber, int column) @@ -342,7 +342,7 @@ void ScriptDirectivesCollector::importFile(const QString &jsfile, const QString import->qualifierIndex = jsGenerator->registerString(module); import->location.line = lineNumber; import->location.column = column; - imports << import; + document->imports << import; } void ScriptDirectivesCollector::importModule(const QString &uri, const QString &version, const QString &module, int lineNumber, int column) @@ -358,7 +358,7 @@ void ScriptDirectivesCollector::importModule(const QString &uri, const QString & import->qualifierIndex = jsGenerator->registerString(module); import->location.line = lineNumber; import->location.column = column; - imports << import; + document->imports << import; } IRBuilder::IRBuilder(const QSet<QString> &illegalNames) @@ -2414,6 +2414,22 @@ QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedO object->qmlSignals->append(s); } + for (uint i = 0; i < serializedObject->nEnums; ++i) { + const QV4::CompiledData::Enum *serializedEnum = serializedObject->enumAt(i); + QmlIR::Enum *e = pool->New<QmlIR::Enum>(); + e->nameIndex = serializedEnum->nameIndex; + e->location = serializedEnum->location; + e->enumValues = pool->New<QmlIR::PoolList<QmlIR::EnumValue> >(); + + for (uint i = 0; i < serializedEnum->nEnumValues; ++i) { + QmlIR::EnumValue *v = pool->New<QmlIR::EnumValue>(); + *static_cast<QV4::CompiledData::EnumValue*>(v) = *serializedEnum->enumValueAt(i); + e->enumValues->append(v); + } + + object->qmlEnums->append(e); + } + const QV4::CompiledData::Property *serializedProperty = serializedObject->propertyTable(); for (uint i = 0; i < serializedObject->nProperties; ++i, ++serializedProperty) { QmlIR::Property *p = pool->New<QmlIR::Property>(); diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index c2cf18e3c4..689b232b1c 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -462,14 +462,14 @@ struct Q_QML_PRIVATE_EXPORT Document static void removeScriptPragmas(QString &script); }; -struct Q_QML_PRIVATE_EXPORT ScriptDirectivesCollector : public QQmlJS::Directives +class Q_QML_PRIVATE_EXPORT ScriptDirectivesCollector : public QQmlJS::Directives { - ScriptDirectivesCollector(QQmlJS::Engine *engine, QV4::Compiler::JSUnitGenerator *unitGenerator); - + QmlIR::Document *document; QQmlJS::Engine *engine; QV4::Compiler::JSUnitGenerator *jsGenerator; - QList<const QV4::CompiledData::Import *> imports; - bool hasPragmaLibrary; + +public: + ScriptDirectivesCollector(QmlIR::Document *doc); void pragmaLibrary() override; void importFile(const QString &jsfile, const QString &module, int lineNumber, int column) override; diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index c281275da1..e831fd48f5 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -2075,6 +2075,8 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, _context->functionIndex = _module->functions.count() - 1; _context->hasDirectEval |= (_context->compilationMode == EvalCode || _context->compilationMode == GlobalCode || _module->debugMode); // Conditional breakpoints are like eval in the function + if (_module->debugMode) // allow the debugger to see overwritten arguments + _context->argumentsCanEscape = true; // When a user writes the following QML signal binding: // onSignal: function() { doSomethingUsefull } diff --git a/src/qml/debugger/qqmlprofilerdefinitions_p.h b/src/qml/debugger/qqmlprofilerdefinitions_p.h index f84a2c44e2..7b972c5d0d 100644 --- a/src/qml/debugger/qqmlprofilerdefinitions_p.h +++ b/src/qml/debugger/qqmlprofilerdefinitions_p.h @@ -96,11 +96,6 @@ struct QQmlProfilerDefinitions { MaximumRangeType }; - enum BindingType { - QmlBinding, - MaximumBindingType - }; - enum PixmapEventType { PixmapSizeKnown, PixmapReferenceCountChanged, @@ -129,8 +124,6 @@ struct QQmlProfilerDefinitions { NumGUIThreadFrameTypes = MaximumSceneGraphFrameType - NumRenderThreadFrameTypes }; - typedef QV4::Profiling::MemoryType MemoryType; - enum ProfileFeature { ProfileJavaScript, ProfileMemory, @@ -162,26 +155,6 @@ struct QQmlProfilerDefinitions { MaximumInputEventType }; - - static ProfileFeature featureFromRangeType(RangeType range) - { - switch (range) { - case Painting: - return ProfilePainting; - case Compiling: - return ProfileCompiling; - case Creating: - return ProfileCreating; - case Binding: - return ProfileBinding; - case HandlingSignal: - return ProfileHandlingSignal; - case Javascript: - return ProfileJavaScript; - default: - return MaximumProfileFeature; - } - } }; QT_END_NAMESPACE diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp index c3e16c4093..9786293e4c 100644 --- a/src/qml/jit/qv4assembler.cpp +++ b/src/qml/jit/qv4assembler.cpp @@ -62,7 +62,6 @@ namespace JIT { #define callHelper(x) PlatformAssemblerCommon::callRuntime(#x, reinterpret_cast<void *>(&x)) const QV4::Value::ValueTypeInternal IntegerTag = QV4::Value::ValueTypeInternal::Integer; -const int IsIntegerConvertible_Shift = QV4::Value::IsIntegerConvertible_Shift; static ReturnedValue toNumberHelper(ReturnedValue v) { @@ -873,7 +872,7 @@ struct PlatformAssembler64 : PlatformAssemblerCommon Jump unopIntPath(std::function<Jump(void)> fastPath) { - urshift64(AccumulatorRegister, TrustedImm32(IsIntegerConvertible_Shift), ScratchRegister); + urshift64(AccumulatorRegister, TrustedImm32(Value::IsIntegerConvertible_Shift), ScratchRegister); Jump accNotIntConvertible = branch32(NotEqual, TrustedImm32(1), ScratchRegister); // both integer diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index b97468ab7b..348ddb25d9 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -409,7 +409,7 @@ bool QJSValue::isObject() const QV4::Value *val = QJSValuePrivate::getValue(this); if (!val) return false; - return val->as<Object>(); + return val->as<QV4::Object>(); } /*! @@ -649,7 +649,7 @@ QVariant QJSValue::toVariant() const QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch); Q_ASSERT(val); - if (Object *o = val->as<Object>()) + if (QV4::Object *o = val->as<QV4::Object>()) return o->engine()->toVariant(*val, /*typeHint*/ -1, /*createJSValueForObjects*/ false); if (String *s = val->stringValue()) @@ -849,7 +849,7 @@ QJSValue QJSValue::prototype() const if (!engine) return QJSValue(); QV4::Scope scope(engine); - ScopedObject o(scope, QJSValuePrivate::getValue(this)->as<Object>()); + ScopedObject o(scope, QJSValuePrivate::getValue(this)->as<QV4::Object>()); if (!o) return QJSValue(); ScopedObject p(scope, o->prototype()); @@ -931,7 +931,7 @@ static bool js_equal(const QString &string, const QV4::Value &value) return RuntimeHelpers::stringToNumber(string) == value.asDouble(); if (value.isBoolean()) return RuntimeHelpers::stringToNumber(string) == double(value.booleanValue()); - if (Object *o = value.objectValue()) { + if (QV4::Object *o = value.objectValue()) { Scope scope(o->engine()); ScopedValue p(scope, RuntimeHelpers::toPrimitive(value, PREFERREDTYPE_HINT)); return js_equal(string, p); diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index bc9b3013d1..5bbe312146 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -55,7 +55,7 @@ #include <wtf/MathExtras.h> -#ifdef Q_OS_LINUX +#if defined(Q_OS_LINUX) && QT_CONFIG(timezone) /* See QTBUG-56899. Although we don't (yet) have a proper way to reset the system zone, the code below, that uses QTimeZone::systemTimeZone(), works diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 5521633db7..835933c043 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -769,16 +769,19 @@ QQmlContextData *ExecutionEngine::callingQmlContext() const QString CppStackFrame::source() const { - return v4Function->sourceFile(); + return v4Function ? v4Function->sourceFile() : QString(); } QString CppStackFrame::function() const { - return v4Function->name()->toQString(); + return v4Function ? v4Function->name()->toQString() : QString(); } int CppStackFrame::lineNumber() const { + if (!v4Function) + return -1; + auto findLine = [](const CompiledData::CodeOffsetToLine &entry, uint offset) { return entry.codeOffset < offset; }; diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index 83e861138b..6fca9ecd45 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -112,6 +112,11 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr internalClass = engine->internalClasses[EngineBase::Class_CallContext]; + // first locals + const quint32_le *localsIndices = compiledFunction->localsTable(); + for (quint32 i = 0; i < compiledFunction->nLocals; ++i) + internalClass = internalClass->addMember(engine->identifierTable->identifier(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable); + Scope scope(engine); ScopedString arg(scope); for (const QString ¶meterName : parameterNames) { @@ -119,10 +124,6 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr internalClass = internalClass->addMember(arg, Attr_NotConfigurable); } nFormals = parameters.size(); - - const quint32_le *localsIndices = compiledFunction->localsTable(); - for (quint32 i = 0; i < compiledFunction->nLocals; ++i) - internalClass = internalClass->addMember(engine->identifierTable->identifier(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable); } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index 9b13d4e341..1fa4bae049 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -101,7 +101,7 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); } # define V4_ENABLE_JIT # endif #elif defined(Q_PROCESSOR_ARM_64) && (QT_POINTER_SIZE == 8) -# if defined(Q_OS_LINUX) || defined(Q_OS_QNX) +# if defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_INTEGRITY) # define V4_ENABLE_JIT # endif //#elif defined(Q_PROCESSOR_MIPS_32) && defined(Q_OS_LINUX) diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index 9da854e7d7..3bfcf358bf 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -533,6 +533,8 @@ void InternalClass::updateInternalClassIdRecursive() id = engine->newInternalClassId(); for (auto &t : transitions) { Q_ASSERT(t.lookup); + if (t.flags == InternalClassTransition::VTableChange || t.flags == InternalClassTransition::PrototypeChange) + continue; t.lookup->updateInternalClassIdRecursive(); } } diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 816c259b9b..d63d42478a 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -102,10 +102,10 @@ QPair<QObject *, int> QObjectMethod::extractQtMethod(const QV4::FunctionObject * return qMakePair((QObject *)nullptr, -1); } -static QPair<QObject *, int> extractQtSignal(const Value &value) +static QPair<QObject *, int> extractQtSignal(const QV4::Value &value) { if (value.isObject()) { - QV4::ExecutionEngine *v4 = value.as<Object>()->engine(); + QV4::ExecutionEngine *v4 = value.as<QV4::Object>()->engine(); QV4::Scope scope(v4); QV4::ScopedFunctionObject function(scope, value); if (function) @@ -1106,7 +1106,7 @@ struct CallArgument { inline void *dataPtr(); inline void initAsType(int type); - inline void fromValue(int type, ExecutionEngine *, const Value &); + inline void fromValue(int type, ExecutionEngine *, const QV4::Value &); inline ReturnedValue toValue(ExecutionEngine *); private: @@ -1304,7 +1304,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType) return 10; } } - } else if (const Object *obj = actual.as<Object>()) { + } else if (const QV4::Object *obj = actual.as<QV4::Object>()) { if (obj->as<QV4::VariantObject>()) { if (conversionType == qMetaTypeId<QVariant>()) return 0; @@ -1720,7 +1720,7 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q || callType == qMetaTypeId<std::vector<QUrl>>() || callType == qMetaTypeId<std::vector<QModelIndex>>()) { queryEngine = true; - const QV4::Object* object = value.as<Object>(); + const QV4::Object* object = value.as<QV4::Object>(); if (callType == qMetaTypeId<std::vector<int>>()) { stdVectorIntPtr = nullptr; fromContainerValue<std::vector<int>>(object, callType, &CallArgument::stdVectorIntPtr, queryEngine); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 0211ad1011..9729228511 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1408,7 +1408,7 @@ ReturnedValue Runtime::method_mod(const Value &left, const Value &right) { TRACE2(left, right); - if (Value::integerCompatible(left, right) && right.integerValue() != 0) { + if (Value::integerCompatible(left, right) && left.integerValue() > 0 && right.integerValue() > 0) { int intRes = left.integerValue() % right.integerValue(); if (intRes != 0 || left.integerValue() >= 0) return Encode(intRes); diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index e5a02fdc22..61176b3706 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -200,7 +200,7 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("trim"), method_trim); } -static Heap::String *thisAsString(ExecutionEngine *v4, const Value *thisObject) +static Heap::String *thisAsString(ExecutionEngine *v4, const QV4::Value *thisObject) { if (String *s = thisObject->stringValue()) return s->d(); @@ -209,7 +209,7 @@ static Heap::String *thisAsString(ExecutionEngine *v4, const Value *thisObject) return thisObject->toString(v4); } -static QString getThisString(ExecutionEngine *v4, const Value *thisObject) +static QString getThisString(ExecutionEngine *v4, const QV4::Value *thisObject) { if (String *s = thisObject->stringValue()) return s->toQString(); diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 6adb25f964..fe7c2bd654 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -345,7 +345,7 @@ static struct InstrCount { if (engine->hasException) \ goto catchException -static inline Heap::CallContext *getScope(Value *stack, int level) +static inline Heap::CallContext *getScope(QV4::Value *stack, int level) { Heap::ExecutionContext *scope = static_cast<ExecutionContext &>(stack[CallData::Context]).d(); while (level > 0) { @@ -362,7 +362,7 @@ static inline const QV4::Value &constant(Function *function, int index) } -static bool compareEqual(Value lhs, Value rhs) +static bool compareEqual(QV4::Value lhs, QV4::Value rhs) { redo: if (lhs.asReturnedValue() == rhs.asReturnedValue()) @@ -376,22 +376,22 @@ static bool compareEqual(Value lhs, Value rhs) } switch (lt) { - case Value::QT_ManagedOrUndefined: + case QV4::Value::QT_ManagedOrUndefined: if (lhs.isUndefined()) return rhs.isNullOrUndefined(); Q_FALLTHROUGH(); - case Value::QT_ManagedOrUndefined1: - case Value::QT_ManagedOrUndefined2: - case Value::QT_ManagedOrUndefined3: + case QV4::Value::QT_ManagedOrUndefined1: + case QV4::Value::QT_ManagedOrUndefined2: + case QV4::Value::QT_ManagedOrUndefined3: // LHS: Managed switch (rt) { - case Value::QT_ManagedOrUndefined: + case QV4::Value::QT_ManagedOrUndefined: if (rhs.isUndefined()) return false; Q_FALLTHROUGH(); - case Value::QT_ManagedOrUndefined1: - case Value::QT_ManagedOrUndefined2: - case Value::QT_ManagedOrUndefined3: { + case QV4::Value::QT_ManagedOrUndefined1: + case QV4::Value::QT_ManagedOrUndefined2: + case QV4::Value::QT_ManagedOrUndefined3: { // RHS: Managed Heap::Base *l = lhs.m(); Heap::Base *r = rhs.m(); @@ -409,12 +409,12 @@ static bool compareEqual(Value lhs, Value rhs) } return false; } - case Value::QT_Empty: + case QV4::Value::QT_Empty: Q_UNREACHABLE(); - case Value::QT_Null: + case QV4::Value::QT_Null: return false; - case Value::QT_Bool: - case Value::QT_Int: + case QV4::Value::QT_Bool: + case QV4::Value::QT_Int: rhs = Primitive::fromDouble(rhs.int_32()); // fall through default: // double @@ -424,22 +424,22 @@ static bool compareEqual(Value lhs, Value rhs) lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT)); } goto redo; - case Value::QT_Empty: + case QV4::Value::QT_Empty: Q_UNREACHABLE(); - case Value::QT_Null: + case QV4::Value::QT_Null: return rhs.isNull(); - case Value::QT_Bool: - case Value::QT_Int: + case QV4::Value::QT_Bool: + case QV4::Value::QT_Int: switch (rt) { - case Value::QT_ManagedOrUndefined: - case Value::QT_ManagedOrUndefined1: - case Value::QT_ManagedOrUndefined2: - case Value::QT_ManagedOrUndefined3: - case Value::QT_Empty: - case Value::QT_Null: + case QV4::Value::QT_ManagedOrUndefined: + case QV4::Value::QT_ManagedOrUndefined1: + case QV4::Value::QT_ManagedOrUndefined2: + case QV4::Value::QT_ManagedOrUndefined3: + case QV4::Value::QT_Empty: + case QV4::Value::QT_Null: Q_UNREACHABLE(); - case Value::QT_Bool: - case Value::QT_Int: + case QV4::Value::QT_Bool: + case QV4::Value::QT_Int: return lhs.int_32() == rhs.int_32(); default: // double return lhs.int_32() == rhs.doubleValue(); @@ -450,29 +450,29 @@ static bool compareEqual(Value lhs, Value rhs) } } -static bool compareEqualInt(Value &accumulator, Value lhs, int rhs) +static bool compareEqualInt(QV4::Value &accumulator, QV4::Value lhs, int rhs) { redo: switch (lhs.quickType()) { - case Value::QT_ManagedOrUndefined: + case QV4::Value::QT_ManagedOrUndefined: if (lhs.isUndefined()) return false; Q_FALLTHROUGH(); - case Value::QT_ManagedOrUndefined1: - case Value::QT_ManagedOrUndefined2: - case Value::QT_ManagedOrUndefined3: + case QV4::Value::QT_ManagedOrUndefined1: + case QV4::Value::QT_ManagedOrUndefined2: + case QV4::Value::QT_ManagedOrUndefined3: // LHS: Managed if (lhs.m()->vtable()->isString) return RuntimeHelpers::stringToNumber(static_cast<String &>(lhs).toQString()) == rhs; accumulator = lhs; lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(accumulator), PREFERREDTYPE_HINT)); goto redo; - case Value::QT_Empty: + case QV4::Value::QT_Empty: Q_UNREACHABLE(); - case Value::QT_Null: + case QV4::Value::QT_Null: return false; - case Value::QT_Bool: - case Value::QT_Int: + case QV4::Value::QT_Bool: + case QV4::Value::QT_Int: return lhs.int_32() == rhs; default: // double return lhs.doubleValue() == rhs; @@ -500,11 +500,11 @@ static bool compareEqualInt(Value &accumulator, Value lhs, int rhs) } \ } while (false) -QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc) +QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObject, const QV4::Value *argv, int argc) { qt_v4ResolvePendingBreakpointsHook(); ExecutionEngine *engine; - Value *stack; + QV4::Value *stack; CppStackFrame frame; frame.originalArguments = argv; frame.originalArgumentsCount = argc; diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index 5dd3278b4c..3dcfa92416 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -536,7 +536,7 @@ QQmlContextData::QQmlContextData() QQmlContextData::QQmlContextData(QQmlContext *ctxt) : engine(nullptr), isInternal(false), isJSContext(false), isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false), - publicContext(ctxt), incubator(nullptr), componentObjectIndex(-1), + stronglyReferencedByParent(false), publicContext(ctxt), incubator(nullptr), componentObjectIndex(-1), contextObject(nullptr), nextChild(nullptr), prevChild(nullptr), expressions(nullptr), contextObjects(nullptr), idValues(nullptr), idValueCount(0), componentAttached(nullptr) @@ -577,7 +577,10 @@ void QQmlContextData::invalidate() while (childContexts) { Q_ASSERT(childContexts != this); - childContexts->invalidate(); + if (childContexts->stronglyReferencedByParent && !--childContexts->refCount) + childContexts->destroy(); + else + childContexts->invalidate(); } if (prevChild) { @@ -672,12 +675,16 @@ void QQmlContextData::destroy() delete this; } -void QQmlContextData::setParent(QQmlContextData *p) +void QQmlContextData::setParent(QQmlContextData *p, bool stronglyReferencedByParent) { if (p == parent) return; if (p) { + Q_ASSERT(!parent); parent = p; + this->stronglyReferencedByParent = stronglyReferencedByParent; + if (stronglyReferencedByParent) + ++refCount; // balanced in QQmlContextData::invalidate() engine = p->engine; nextChild = p->childContexts; if (nextChild) nextChild->prevChild = &nextChild; diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h index 5dfee48848..290b7fc7ee 100644 --- a/src/qml/qml/qqmlcontext_p.h +++ b/src/qml/qml/qqmlcontext_p.h @@ -126,7 +126,7 @@ public: QQmlContextData *parent = nullptr; QQmlEngine *engine; - void setParent(QQmlContextData *); + void setParent(QQmlContextData *, bool stronglyReferencedByParent = false); void refreshExpressions(); void addObject(QObject *); @@ -144,7 +144,8 @@ public: quint32 unresolvedNames:1; // True if expressions in this context failed to resolve a toplevel name quint32 hasEmittedDestruction:1; quint32 isRootObjectInCreation:1; - quint32 dummy:26; + quint32 stronglyReferencedByParent:1; + quint32 dummy:25; QQmlContext *publicContext; // The incubator that is constructing this context if any diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 7e11177caa..b27bf3779a 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1196,6 +1196,8 @@ void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index) support. The factory must be set before executing the engine. + + \note QQmlEngine does not take ownership of the factory. */ void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory) { diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 8fda7f6f77..d842a7795f 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -424,7 +424,7 @@ QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQm d->version_min = type.versionMinor; d->extraData.sd->singletonInstanceInfo = new SingletonInstanceInfo; - d->extraData.sd->singletonInstanceInfo->url = type.url; + d->extraData.sd->singletonInstanceInfo->url = QQmlTypeLoader::normalize(type.url); d->extraData.sd->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName); } @@ -477,7 +477,7 @@ QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQm d->version_maj = type.versionMajor; d->version_min = type.versionMinor; - d->extraData.fd->url = type.url; + d->extraData.fd->url = QQmlTypeLoader::normalize(type.url); } QQmlType::QQmlType() @@ -1710,7 +1710,7 @@ QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::Registe addTypeToData(dtype.priv(), data); QQmlMetaTypeData::Files *files = fileImport ? &(data->urlToType) : &(data->urlToNonFileImportType); - files->insertMulti(type.url, dtype.priv()); + files->insertMulti(QQmlTypeLoader::normalize(type.url), dtype.priv()); return dtype; } @@ -1731,7 +1731,7 @@ QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterComposit addTypeToData(dtype.priv(), data); QQmlMetaTypeData::Files *files = fileImport ? &(data->urlToType) : &(data->urlToNonFileImportType); - files->insertMulti(type.url, dtype.priv()); + files->insertMulti(QQmlTypeLoader::normalize(type.url), dtype.priv()); return dtype; } @@ -2253,8 +2253,9 @@ QQmlType QQmlMetaType::qmlType(int userType) Returns null if no such type is registered. */ -QQmlType QQmlMetaType::qmlType(const QUrl &url, bool includeNonFileImports /* = false */) +QQmlType QQmlMetaType::qmlType(const QUrl &unNormalizedUrl, bool includeNonFileImports /* = false */) { + const QUrl url = QQmlTypeLoader::normalize(unNormalizedUrl); QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index cd7afc8a01..51bf485a3e 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -96,7 +96,7 @@ public: static QQmlType qmlType(const QMetaObject *); static QQmlType qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor); static QQmlType qmlType(int); - static QQmlType qmlType(const QUrl &url, bool includeNonFileImports = false); + static QQmlType qmlType(const QUrl &unNormalizedUrl, bool includeNonFileImports = false); static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject); static QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion); diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 7051fb51da..5aaf79c9e5 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -1217,9 +1217,9 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo } ddata = QQmlData::get(instance, /*create*/true); - ddata->lineNumber = obj->location.line; - ddata->columnNumber = obj->location.column; } + ddata->lineNumber = obj->location.line; + ddata->columnNumber = obj->location.column; ddata->setImplicitDestructible(); if (static_cast<quint32>(index) == /*root object*/0 || ddata->rootObjectInCreation) { diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 1cab827b9f..f4c612b187 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -358,9 +358,8 @@ qreal QQmlDataBlob::progress() const /*! Returns the physical url of the data. Initially this is the same as -finalUrl(), but if a network redirect happens while fetching the data, this url -is updated to reflect the new location. Also, if a URL interceptor is set, it -will work on this URL and leave finalUrl() alone. +finalUrl(), but if a URL interceptor is set, it will work on this URL +and leave finalUrl() alone. \sa finalUrl() */ @@ -381,8 +380,12 @@ QString QQmlDataBlob::urlString() const Returns the logical URL to be used for resolving further URLs referred to in the code. -This is the blob url passed to the constructor. If a network redirect -happens while fetching the data, this url remains the same. +This is the blob url passed to the constructor. If a URL interceptor rewrites +the URL, this one stays the same. If a network redirect happens while fetching +the data, this url is updated to reflect the new location. Therefore, if both +an interception and a redirection happen, the final url will indirectly +incorporate the result of the interception, potentially breaking further +lookups. \sa url() */ @@ -1184,15 +1187,15 @@ void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply) QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); if (redirect.isValid()) { QUrl url = reply->url().resolved(redirect.toUrl()); - blob->m_url = url; - blob->m_urlString.clear(); + blob->m_finalUrl = url; + blob->m_finalUrlString.clear(); QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(url)); QObject *nrp = m_thread->networkReplyProxy(); QObject::connect(reply, SIGNAL(finished()), nrp, SLOT(finished())); m_networkReplies.insert(reply, blob); #ifdef DATABLOB_DEBUG - qWarning("QQmlDataBlob: redirected to %s", qPrintable(blob->urlString())); + qWarning("QQmlDataBlob: redirected to %s", qPrintable(blob->finalUrlString())); #endif return; } @@ -1648,14 +1651,24 @@ QQmlImportDatabase *QQmlTypeLoader::importDatabase() const return &QQmlEnginePrivate::get(engine())->importDatabase; } +QUrl QQmlTypeLoader::normalize(const QUrl &unNormalizedUrl) +{ + QUrl normalized(unNormalizedUrl); + if (normalized.scheme() == QLatin1String("qrc")) + normalized.setHost(QString()); // map qrc:///a.qml to qrc:/a.qml + return normalized; +} + /*! Returns a QQmlTypeData for the specified \a url. The QQmlTypeData may be cached. */ -QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode) +QQmlTypeData *QQmlTypeLoader::getType(const QUrl &unNormalizedUrl, Mode mode) { - Q_ASSERT(!url.isRelative() && - (QQmlFile::urlToLocalFileOrQrc(url).isEmpty() || - !QDir::isRelativePath(QQmlFile::urlToLocalFileOrQrc(url)))); + Q_ASSERT(!unNormalizedUrl.isRelative() && + (QQmlFile::urlToLocalFileOrQrc(unNormalizedUrl).isEmpty() || + !QDir::isRelativePath(QQmlFile::urlToLocalFileOrQrc(unNormalizedUrl)))); + + const QUrl url = normalize(unNormalizedUrl); LockHolder<QQmlTypeLoader> holder(this); @@ -1713,11 +1726,13 @@ QQmlTypeData *QQmlTypeLoader::getType(const QByteArray &data, const QUrl &url, M /*! Return a QQmlScriptBlob for \a url. The QQmlScriptData may be cached. */ -QQmlScriptBlob *QQmlTypeLoader::getScript(const QUrl &url) +QQmlScriptBlob *QQmlTypeLoader::getScript(const QUrl &unNormalizedUrl) { - Q_ASSERT(!url.isRelative() && - (QQmlFile::urlToLocalFileOrQrc(url).isEmpty() || - !QDir::isRelativePath(QQmlFile::urlToLocalFileOrQrc(url)))); + Q_ASSERT(!unNormalizedUrl.isRelative() && + (QQmlFile::urlToLocalFileOrQrc(unNormalizedUrl).isEmpty() || + !QDir::isRelativePath(QQmlFile::urlToLocalFileOrQrc(unNormalizedUrl)))); + + const QUrl url = normalize(unNormalizedUrl); LockHolder<QQmlTypeLoader> holder(this); @@ -1833,15 +1848,7 @@ QString QQmlTypeLoader::absoluteFilePath(const QString &path) if (*value) absoluteFilePath = path; } else { - bool exists = false; -#ifdef Q_OS_UNIX - struct stat statBuf; - // XXX Avoid encoding entire path. Should store encoded dirpath in cache - if (::stat(QFile::encodeName(path).constData(), &statBuf) == 0) - exists = S_ISREG(statBuf.st_mode); -#else - exists = QFile::exists(path); -#endif + bool exists = QFile::exists(path); fileSet->insert(fileName, new bool(exists)); if (exists) absoluteFilePath = path; @@ -3010,7 +3017,7 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data) return; } - QmlIR::ScriptDirectivesCollector collector(&irUnit.jsParserEngine, &irUnit.jsGenerator); + QmlIR::ScriptDirectivesCollector collector(&irUnit); QList<QQmlError> errors; QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Script::precompile( @@ -3026,9 +3033,6 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data) unit.adopt(new QV4::CompiledData::CompilationUnit); } irUnit.javaScriptCompilationUnit = unit; - irUnit.imports = collector.imports; - if (collector.hasPragmaLibrary) - irUnit.jsModule.unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary; QmlIR::QmlUnitGenerator qmlGenerator; QV4::CompiledData::Unit *unitData = qmlGenerator.generate(irUnit); diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 5988632547..e75719866d 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -305,10 +305,12 @@ public: QQmlImportDatabase *importDatabase() const; - QQmlTypeData *getType(const QUrl &url, Mode mode = PreferSynchronous); + static QUrl normalize(const QUrl &unNormalizedUrl); + + QQmlTypeData *getType(const QUrl &unNormalizedUrl, Mode mode = PreferSynchronous); QQmlTypeData *getType(const QByteArray &, const QUrl &url, Mode mode = PreferSynchronous); - QQmlScriptBlob *getScript(const QUrl &); + QQmlScriptBlob *getScript(const QUrl &unNormalizedUrl); QQmlQmldirData *getQmldir(const QUrl &); QString absoluteFilePath(const QString &path); diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 9e7c84011b..221754a29a 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -1697,7 +1697,7 @@ ReturnedValue ConsoleObject::method_count(const FunctionObject *b, const Value * QString scriptName = frame->source(); - int value = v8engine->consoleCountHelper(scriptName, frame->lineNumber(), -1); + int value = v8engine->consoleCountHelper(scriptName, frame->lineNumber(), 0); QString message = name + QLatin1String(": ") + QString::number(value); QMessageLogger(qPrintable(scriptName), frame->lineNumber(), diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 44166e4aa8..eb02e8045a 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -874,10 +874,11 @@ void QQmlDelegateModelPrivate::removeCacheItem(QQmlDelegateModelItem *cacheItem) void QQmlDelegateModelPrivate::incubatorStatusChanged(QQDMIncubationTask *incubationTask, QQmlIncubator::Status status) { - Q_Q(QQmlDelegateModel); if (!isDoneIncubating(status)) return; + const QList<QQmlError> incubationTaskErrors = incubationTask->errors(); + QQmlDelegateModelItem *cacheItem = incubationTask->incubating; cacheItem->incubationTask = nullptr; incubationTask->incubating = nullptr; @@ -891,7 +892,7 @@ void QQmlDelegateModelPrivate::incubatorStatusChanged(QQDMIncubationTask *incuba emitCreatedItem(incubationTask, cacheItem->object); cacheItem->releaseObject(); } else if (status == QQmlIncubator::Error) { - qmlWarning(q, m_delegate->errors()) << "Error creating delegate"; + qmlWarning(m_delegate, incubationTaskErrors + m_delegate->errors()) << "Error creating delegate"; } if (!cacheItem->isObjectReferenced()) { @@ -988,7 +989,7 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, QQ if (QQmlAdaptorModelProxyInterface *proxy = qobject_cast<QQmlAdaptorModelProxyInterface *>(cacheItem)) { ctxt = new QQmlContextData; - ctxt->setParent(cacheItem->contextData); + ctxt->setParent(cacheItem->contextData, /*stronglyReferencedByParent*/true); ctxt->contextObject = proxy->proxiedObject(); } } diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index c4e33d572d..877968faf4 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -1463,8 +1463,8 @@ void ModelNodeMetaObject::emitDirectNotifies(const int *changedRoles, int roleCo QQmlData *ddata = QQmlData::get(object(), /*create*/false); if (!ddata) return; - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(qmlEngine(m_model)); - if (!ep) + // There's nothing to emit if we're a list model in a worker thread. + if (!qmlEngine(m_model)) return; for (int i = 0; i < roleCount; ++i) { const int changedRole = changedRoles[i]; diff --git a/src/qmldebug/qmldebug.pro b/src/qmldebug/qmldebug.pro index 2539414d8f..2c1b71797d 100644 --- a/src/qmldebug/qmldebug.pro +++ b/src/qmldebug/qmldebug.pro @@ -1,5 +1,5 @@ TARGET = QtQmlDebug -QT = core-private network packetprotocol-private qml-private +QT = core-private network packetprotocol-private CONFIG += static internal_module load(qt_module) @@ -28,4 +28,5 @@ HEADERS += \ qqmlprofilereventlocation_p.h \ qqmlprofilereventreceiver_p.h \ qqmlprofilereventtype_p.h \ - qqmlprofilertypedevent_p.h + qqmlprofilertypedevent_p.h \ + qqmlprofilerclientdefinitions_p.h diff --git a/src/qmldebug/qqmlenginecontrolclient.cpp b/src/qmldebug/qqmlenginecontrolclient.cpp index 13f216ce38..45d672d4bc 100644 --- a/src/qmldebug/qqmlenginecontrolclient.cpp +++ b/src/qmldebug/qqmlenginecontrolclient.cpp @@ -41,7 +41,6 @@ #include "qqmlenginecontrolclient_p_p.h" #include "qqmldebugconnection_p.h" -#include <private/qqmldebugserviceinterfaces_p.h> #include <private/qpacket_p.h> QT_BEGIN_NAMESPACE @@ -142,7 +141,7 @@ void QQmlEngineControlClient::messageReceived(const QByteArray &data) } QQmlEngineControlClientPrivate::QQmlEngineControlClientPrivate(QQmlDebugConnection *connection) : - QQmlDebugClientPrivate(QQmlEngineControlService::s_key, connection) + QQmlDebugClientPrivate(QLatin1String("EngineControl"), connection) { } diff --git a/src/qmldebug/qqmlprofilerclient.cpp b/src/qmldebug/qqmlprofilerclient.cpp index d2a2d24f13..661b43f164 100644 --- a/src/qmldebug/qqmlprofilerclient.cpp +++ b/src/qmldebug/qqmlprofilerclient.cpp @@ -39,7 +39,6 @@ #include "qqmlprofilerclient_p_p.h" #include "qqmldebugconnection_p.h" -#include <private/qqmldebugserviceinterfaces_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qmldebug/qqmlprofilerclient_p.h b/src/qmldebug/qqmlprofilerclient_p.h index 68a32a1a5a..7b8e286f5b 100644 --- a/src/qmldebug/qqmlprofilerclient_p.h +++ b/src/qmldebug/qqmlprofilerclient_p.h @@ -43,8 +43,8 @@ #include "qqmldebugclient_p.h" #include "qqmlprofilereventlocation_p.h" #include "qqmlprofilereventreceiver_p.h" +#include "qqmlprofilerclientdefinitions_p.h" -#include <private/qqmlprofilerdefinitions_p.h> #include <private/qpacket_p.h> // @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE class QQmlProfilerClientPrivate; -class QQmlProfilerClient : public QQmlDebugClient, public QQmlProfilerDefinitions +class QQmlProfilerClient : public QQmlDebugClient { Q_OBJECT Q_DECLARE_PRIVATE(QQmlProfilerClient) diff --git a/src/qmldebug/qqmlprofilerclient_p_p.h b/src/qmldebug/qqmlprofilerclient_p_p.h index 0caef8e448..994c08cafc 100644 --- a/src/qmldebug/qqmlprofilerclient_p_p.h +++ b/src/qmldebug/qqmlprofilerclient_p_p.h @@ -45,10 +45,10 @@ #include "qqmlenginecontrolclient_p.h" #include "qqmlprofilerclient_p.h" #include "qqmlprofilertypedevent_p.h" - -#include <private/qqmlprofilerdefinitions_p.h> +#include "qqmlprofilerclientdefinitions_p.h" #include <QtCore/qqueue.h> +#include <QtCore/qstack.h> // // W A R N I N G @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE -class QQmlProfilerClientPrivate : public QQmlDebugClientPrivate, public QQmlProfilerDefinitions { +class QQmlProfilerClientPrivate : public QQmlDebugClientPrivate { Q_DECLARE_PUBLIC(QQmlProfilerClient) public: QQmlProfilerClientPrivate(QQmlDebugConnection *connection, diff --git a/src/qmldebug/qqmlprofilerclientdefinitions_p.h b/src/qmldebug/qqmlprofilerclientdefinitions_p.h new file mode 100644 index 0000000000..be1c6318af --- /dev/null +++ b/src/qmldebug/qqmlprofilerclientdefinitions_p.h @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLPROFILERCLIENTDEFINITIONS_P_H +#define QQMLPROFILERCLIENTDEFINITIONS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +enum Message { + Event, + RangeStart, + RangeData, + RangeLocation, + RangeEnd, + Complete, // end of transmission + PixmapCacheEvent, + SceneGraphFrame, + MemoryAllocation, + DebugMessage, + + MaximumMessage +}; + +enum EventType { + FramePaint, + Mouse, + Key, + AnimationFrame, + EndTrace, + StartTrace, + + MaximumEventType +}; + +enum RangeType { + Painting, + Compiling, + Creating, + Binding, //running a binding + HandlingSignal, //running a signal handler + Javascript, + + MaximumRangeType +}; + +enum PixmapEventType { + PixmapSizeKnown, + PixmapReferenceCountChanged, + PixmapCacheCountChanged, + PixmapLoadingStarted, + PixmapLoadingFinished, + PixmapLoadingError, + + MaximumPixmapEventType +}; + +enum SceneGraphFrameType { + SceneGraphRendererFrame, // Render Thread + SceneGraphAdaptationLayerFrame, // Render Thread + SceneGraphContextFrame, // Render Thread + SceneGraphRenderLoopFrame, // Render Thread + SceneGraphTexturePrepare, // Render Thread + SceneGraphTextureDeletion, // Render Thread + SceneGraphPolishAndSync, // GUI Thread + SceneGraphWindowsRenderShow, // Unused + SceneGraphWindowsAnimations, // GUI Thread + SceneGraphPolishFrame, // GUI Thread + + MaximumSceneGraphFrameType, + NumRenderThreadFrameTypes = SceneGraphPolishAndSync, + NumGUIThreadFrameTypes = MaximumSceneGraphFrameType - NumRenderThreadFrameTypes +}; + +enum MemoryType { + HeapPage, + LargeItem, + SmallItem +}; + +enum ProfileFeature { + ProfileJavaScript, + ProfileMemory, + ProfilePixmapCache, + ProfileSceneGraph, + ProfileAnimations, + ProfilePainting, + ProfileCompiling, + ProfileCreating, + ProfileBinding, + ProfileHandlingSignal, + ProfileInputEvents, + ProfileDebugMessages, + + MaximumProfileFeature +}; + +enum InputEventType { + InputKeyPress, + InputKeyRelease, + InputKeyUnknown, + + InputMousePress, + InputMouseRelease, + InputMouseMove, + InputMouseDoubleClick, + InputMouseWheel, + InputMouseUnknown, + + MaximumInputEventType +}; + +QT_END_NAMESPACE + +#endif // QQMLPROFILERCLIENTDEFINITIONS_P_H diff --git a/src/qmldebug/qqmlprofilerevent_p.h b/src/qmldebug/qqmlprofilerevent_p.h index 49a0c9e347..1e205d8dbb 100644 --- a/src/qmldebug/qqmlprofilerevent_p.h +++ b/src/qmldebug/qqmlprofilerevent_p.h @@ -40,7 +40,7 @@ #ifndef QQMLPROFILEREVENT_P_H #define QQMLPROFILEREVENT_P_H -#include <private/qqmlprofilerdefinitions_p.h> +#include "qqmlprofilerclientdefinitions_p.h" #include <QtCore/qstring.h> #include <QtCore/qbytearray.h> @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE -struct QQmlProfilerEvent : public QQmlProfilerDefinitions { +struct QQmlProfilerEvent { QQmlProfilerEvent() : m_timestamp(-1), m_typeIndex(-1), m_dataType(Inline8Bit), m_dataLength(0) {} diff --git a/src/qmldebug/qqmlprofilereventtype.cpp b/src/qmldebug/qqmlprofilereventtype.cpp index b0aad3fc5b..c92e914d74 100644 --- a/src/qmldebug/qqmlprofilereventtype.cpp +++ b/src/qmldebug/qqmlprofilereventtype.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qqmlprofilereventtype_p.h" +#include "qqmlprofilerclientdefinitions_p.h" #include <QtCore/qdatastream.h> @@ -49,8 +50,8 @@ QDataStream &operator>>(QDataStream &stream, QQmlProfilerEventType &type) quint8 rangeType; stream >> type.m_displayName >> type.m_data >> type.m_location >> message >> rangeType >> type.m_detailType; - type.m_message = static_cast<QQmlProfilerDefinitions::Message>(message); - type.m_rangeType = static_cast<QQmlProfilerDefinitions::RangeType>(rangeType); + type.m_message = static_cast<Message>(message); + type.m_rangeType = static_cast<RangeType>(rangeType); return stream; } @@ -61,7 +62,7 @@ QDataStream &operator<<(QDataStream &stream, const QQmlProfilerEventType &type) << type.m_detailType; } -QQmlProfilerDefinitions::ProfileFeature QQmlProfilerEventType::feature() const +ProfileFeature QQmlProfilerEventType::feature() const { switch (m_message) { case Event: { @@ -84,7 +85,24 @@ QQmlProfilerDefinitions::ProfileFeature QQmlProfilerEventType::feature() const case DebugMessage: return ProfileDebugMessages; default: - return featureFromRangeType(m_rangeType); + break; + } + + switch (m_rangeType) { + case Painting: + return ProfilePainting; + case Compiling: + return ProfileCompiling; + case Creating: + return ProfileCreating; + case Binding: + return ProfileBinding; + case HandlingSignal: + return ProfileHandlingSignal; + case Javascript: + return ProfileJavaScript; + default: + return MaximumProfileFeature; } } diff --git a/src/qmldebug/qqmlprofilereventtype_p.h b/src/qmldebug/qqmlprofilereventtype_p.h index 7bd67f9ca8..7189df53ef 100644 --- a/src/qmldebug/qqmlprofilereventtype_p.h +++ b/src/qmldebug/qqmlprofilereventtype_p.h @@ -41,8 +41,7 @@ #define QQMLPROFILEREVENTTYPE_P_H #include "qqmlprofilereventlocation_p.h" - -#include <private/qqmlprofilerdefinitions_p.h> +#include "qqmlprofilerclientdefinitions_p.h" #include <QtCore/qstring.h> #include <QtCore/qmetatype.h> @@ -61,7 +60,7 @@ QT_BEGIN_NAMESPACE -class QQmlProfilerEventType : public QQmlProfilerDefinitions { +class QQmlProfilerEventType { public: QQmlProfilerEventType(Message message = MaximumMessage, RangeType rangeType = MaximumRangeType, int detailType = -1, diff --git a/src/qmldebug/qqmlprofilertypedevent.cpp b/src/qmldebug/qqmlprofilertypedevent.cpp index 9b00481e17..31a36bd052 100644 --- a/src/qmldebug/qqmlprofilertypedevent.cpp +++ b/src/qmldebug/qqmlprofilertypedevent.cpp @@ -38,6 +38,8 @@ ****************************************************************************/ #include "qqmlprofilertypedevent_p.h" +#include "qqmlprofilerclientdefinitions_p.h" + #include <QtCore/qvarlengtharray.h> QT_BEGIN_NAMESPACE @@ -50,15 +52,15 @@ QDataStream &operator>>(QDataStream &stream, QQmlProfilerTypedEvent &event) stream >> time >> messageType; - if (messageType < 0 || messageType > QQmlProfilerDefinitions::MaximumMessage) - messageType = QQmlProfilerDefinitions::MaximumMessage; + if (messageType < 0 || messageType > MaximumMessage) + messageType = MaximumMessage; - QQmlProfilerDefinitions::RangeType rangeType = QQmlProfilerDefinitions::MaximumRangeType; + RangeType rangeType = MaximumRangeType; if (!stream.atEnd()) { stream >> subtype; - rangeType = static_cast<QQmlProfilerDefinitions::RangeType>(subtype); - if (rangeType < 0 || rangeType > QQmlProfilerDefinitions::MaximumRangeType) - rangeType = QQmlProfilerDefinitions::MaximumRangeType; + rangeType = static_cast<RangeType>(subtype); + if (rangeType < 0 || rangeType > MaximumRangeType) + rangeType = MaximumRangeType; } else { subtype = -1; } @@ -68,13 +70,13 @@ QDataStream &operator>>(QDataStream &stream, QQmlProfilerTypedEvent &event) event.serverTypeId = 0; switch (messageType) { - case QQmlProfilerDefinitions::Event: { + case Event: { event.type = QQmlProfilerEventType( - static_cast<QQmlProfilerDefinitions::Message>(messageType), - QQmlProfilerDefinitions::MaximumRangeType, subtype); + static_cast<Message>(messageType), + MaximumRangeType, subtype); switch (subtype) { - case QQmlProfilerDefinitions::StartTrace: - case QQmlProfilerDefinitions::EndTrace: { + case StartTrace: + case EndTrace: { QVarLengthArray<qint32> engineIds; while (!stream.atEnd()) { qint32 id; @@ -84,7 +86,7 @@ QDataStream &operator>>(QDataStream &stream, QQmlProfilerTypedEvent &event) event.event.setNumbers<QVarLengthArray<qint32>, qint32>(engineIds); break; } - case QQmlProfilerDefinitions::AnimationFrame: { + case AnimationFrame: { qint32 frameRate, animationCount; qint32 threadId; stream >> frameRate >> animationCount; @@ -96,11 +98,9 @@ QDataStream &operator>>(QDataStream &stream, QQmlProfilerTypedEvent &event) event.event.setNumbers<qint32>({frameRate, animationCount, threadId}); break; } - case QQmlProfilerDefinitions::Mouse: - case QQmlProfilerDefinitions::Key: - int inputType = (subtype == QQmlProfilerDefinitions::Key - ? QQmlProfilerDefinitions::InputKeyUnknown - : QQmlProfilerDefinitions::InputMouseUnknown); + case Mouse: + case Key: + int inputType = (subtype == Key ? InputKeyUnknown : InputMouseUnknown); if (!stream.atEnd()) stream >> inputType; qint32 a = -1; @@ -116,13 +116,13 @@ QDataStream &operator>>(QDataStream &stream, QQmlProfilerTypedEvent &event) break; } - case QQmlProfilerDefinitions::Complete: { + case Complete: { event.type = QQmlProfilerEventType( - static_cast<QQmlProfilerDefinitions::Message>(messageType), - QQmlProfilerDefinitions::MaximumRangeType, subtype); + static_cast<Message>(messageType), + MaximumRangeType, subtype); break; } - case QQmlProfilerDefinitions::SceneGraphFrame: { + case SceneGraphFrame: { QVarLengthArray<qint64> params; qint64 param; @@ -132,41 +132,40 @@ QDataStream &operator>>(QDataStream &stream, QQmlProfilerTypedEvent &event) } event.type = QQmlProfilerEventType( - static_cast<QQmlProfilerDefinitions::Message>(messageType), - QQmlProfilerDefinitions::MaximumRangeType, subtype); + static_cast<Message>(messageType), + MaximumRangeType, subtype); event.event.setNumbers<QVarLengthArray<qint64>, qint64>(params); break; } - case QQmlProfilerDefinitions::PixmapCacheEvent: { + case PixmapCacheEvent: { qint32 width = 0, height = 0, refcount = 0; QString filename; stream >> filename; - if (subtype == QQmlProfilerDefinitions::PixmapReferenceCountChanged - || subtype == QQmlProfilerDefinitions::PixmapCacheCountChanged) { + if (subtype == PixmapReferenceCountChanged || subtype == PixmapCacheCountChanged) { stream >> refcount; - } else if (subtype == QQmlProfilerDefinitions::PixmapSizeKnown) { + } else if (subtype == PixmapSizeKnown) { stream >> width >> height; refcount = 1; } event.type = QQmlProfilerEventType( - static_cast<QQmlProfilerDefinitions::Message>(messageType), - QQmlProfilerDefinitions::MaximumRangeType, subtype, + static_cast<Message>(messageType), + MaximumRangeType, subtype, QQmlProfilerEventLocation(filename, 0, 0)); event.event.setNumbers<qint32>({width, height, refcount}); break; } - case QQmlProfilerDefinitions::MemoryAllocation: { + case MemoryAllocation: { qint64 delta; stream >> delta; event.type = QQmlProfilerEventType( - static_cast<QQmlProfilerDefinitions::Message>(messageType), - QQmlProfilerDefinitions::MaximumRangeType, subtype); + static_cast<Message>(messageType), + MaximumRangeType, subtype); event.event.setNumbers<qint64>({delta}); break; } - case QQmlProfilerDefinitions::RangeStart: { + case RangeStart: { if (!stream.atEnd()) { qint64 typeId; stream >> typeId; @@ -175,22 +174,22 @@ QDataStream &operator>>(QDataStream &stream, QQmlProfilerTypedEvent &event) // otherwise it's the old binding type of 4 bytes } - event.type = QQmlProfilerEventType(QQmlProfilerDefinitions::MaximumMessage, rangeType, -1); - event.event.setRangeStage(QQmlProfilerDefinitions::RangeStart); + event.type = QQmlProfilerEventType(MaximumMessage, rangeType, -1); + event.event.setRangeStage(RangeStart); break; } - case QQmlProfilerDefinitions::RangeData: { + case RangeData: { QString data; stream >> data; - event.type = QQmlProfilerEventType(QQmlProfilerDefinitions::MaximumMessage, rangeType, -1, + event.type = QQmlProfilerEventType(MaximumMessage, rangeType, -1, QQmlProfilerEventLocation(), data); - event.event.setRangeStage(QQmlProfilerDefinitions::RangeData); + event.event.setRangeStage(RangeData); if (!stream.atEnd()) stream >> event.serverTypeId; break; } - case QQmlProfilerDefinitions::RangeLocation: { + case RangeLocation: { QString filename; qint32 line = 0; qint32 column = 0; @@ -202,21 +201,21 @@ QDataStream &operator>>(QDataStream &stream, QQmlProfilerTypedEvent &event) stream >> event.serverTypeId; } - event.type = QQmlProfilerEventType(QQmlProfilerDefinitions::MaximumMessage, rangeType, -1, + event.type = QQmlProfilerEventType(MaximumMessage, rangeType, -1, QQmlProfilerEventLocation(filename, line, column)); - event.event.setRangeStage(QQmlProfilerDefinitions::RangeLocation); + event.event.setRangeStage(RangeLocation); break; } - case QQmlProfilerDefinitions::RangeEnd: { - event.type = QQmlProfilerEventType(QQmlProfilerDefinitions::MaximumMessage, rangeType, -1); - event.event.setRangeStage(QQmlProfilerDefinitions::RangeEnd); + case RangeEnd: { + event.type = QQmlProfilerEventType(MaximumMessage, rangeType, -1); + event.event.setRangeStage(RangeEnd); break; } default: event.event.setNumbers<char>({}); event.type = QQmlProfilerEventType( - static_cast<QQmlProfilerDefinitions::Message>(messageType), - QQmlProfilerDefinitions::MaximumRangeType, subtype); + static_cast<Message>(messageType), + MaximumRangeType, subtype); break; } diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp index a02a0a806d..8b9ff4c5cd 100644 --- a/src/qmltest/quicktest.cpp +++ b/src/qmltest/quicktest.cpp @@ -207,7 +207,11 @@ public: TestCaseCollector(const QFileInfo &fileInfo, QQmlEngine *engine) { - QQmlComponent component(engine, fileInfo.absoluteFilePath()); + QString path = fileInfo.absoluteFilePath(); + if (path.startsWith(QLatin1String(":/"))) + path.prepend(QLatin1String("qrc")); + + QQmlComponent component(engine, path); m_errors += component.errors(); if (component.isReady()) { @@ -534,7 +538,7 @@ int quick_test_main_with_setup(int argc, char **argv, const char *name, const ch QTestRootObject::instance()->init(); QString path = fi.absoluteFilePath(); if (path.startsWith(QLatin1String(":/"))) - view.setSource(QUrl(QLatin1String("qrc:") + path.midRef(2))); + view.setSource(QUrl(QLatin1String("qrc:") + path.midRef(1))); else view.setSource(QUrl::fromLocalFile(path)); diff --git a/src/quick/configure.json b/src/quick/configure.json index b77ea863b3..ea1d49baad 100644 --- a/src/quick/configure.json +++ b/src/quick/configure.json @@ -120,6 +120,7 @@ "label": "Path support", "purpose": "Provides Path elements.", "section": "Qt Quick", + "condition": "features.quick-shadereffect", "output": [ "privateFeature" ] diff --git a/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc b/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc index e70791d1c9..30aca38678 100644 --- a/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc +++ b/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc @@ -29,6 +29,7 @@ \page qtquick-bestpractices.html \title Best Practices for QML and Qt Quick \brief Lists best practices for working with QML and Qt Quick +\ingroup best-practices Despite all of the benefits that QML and Qt Quick offer, they can be challenging in certain situations. The following sections elaborate on some of @@ -317,8 +318,8 @@ component loaded by the engine. Context properties are useful for objects that must be available as soon as the QML is loaded and cannot be instantiated in QML. -\l {Integrating QML and C++} demonstrates an alternative approach where QML is -made aware of a C++ type so that it can instantiate it itself. +For a quick guide to choosing the correct approach to expose C++ types to QML, +see \l {Choosing the Correct Integration Method Between C++ and QML}. \section2 Related Information \list diff --git a/src/quick/handlers/qquickmultipointhandler.cpp b/src/quick/handlers/qquickmultipointhandler.cpp index b126b93211..d595b4c9b4 100644 --- a/src/quick/handlers/qquickmultipointhandler.cpp +++ b/src/quick/handlers/qquickmultipointhandler.cpp @@ -76,8 +76,10 @@ bool QQuickMultiPointHandler::wantsPointerEvent(QQuickPointerEvent *event) if (!QQuickPointerDeviceHandler::wantsPointerEvent(event)) return false; +#if QT_CONFIG(gestures) if (event->asPointerNativeGestureEvent()) return true; +#endif if (sameAsCurrentPoints(event)) return true; diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp index 155822197f..fc69accffc 100644 --- a/src/quick/handlers/qquickpinchhandler.cpp +++ b/src/quick/handlers/qquickpinchhandler.cpp @@ -248,6 +248,7 @@ bool QQuickPinchHandler::wantsPointerEvent(QQuickPointerEvent *event) if (!QQuickMultiPointHandler::wantsPointerEvent(event)) return false; +#if QT_CONFIG(gestures) if (const auto gesture = event->asPointerNativeGestureEvent()) { if (minimumPointCount() == 2) { switch (gesture->type()) { @@ -263,6 +264,7 @@ bool QQuickPinchHandler::wantsPointerEvent(QQuickPointerEvent *event) return false; } } +#endif return true; } @@ -319,6 +321,7 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event) } qreal dist = 0; +#if QT_CONFIG(gestures) if (const auto gesture = event->asPointerNativeGestureEvent()) { switch (gesture->type()) { case Qt::EndNativeGesture: @@ -349,7 +352,9 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event) m_centroidVelocity = QVector2D(); m_activeTranslation = QVector2D(); } - } else { + } else +#endif // QT_CONFIG(gestures) + { bool containsReleasedPoints = event->isReleaseEvent(); if (!active()) { // Verify that at least one of the points has moved beyond threshold needed to activate the handler diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index af8048f2e4..addcf9b540 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -1637,7 +1637,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(const QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>()); QV4::ScopedObject p(scope, ed->gradientProto.value()); gradient->setPrototype(p); - *gradient->d()->brush = QRadialGradient(QPointF(x1, y1), r0+r1, QPointF(x0, y0)); + *gradient->d()->brush = QRadialGradient(QPointF(x1, y1), r1, QPointF(x0, y0), r0); RETURN_RESULT(*gradient); } diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp index 26dfdb07a6..075c4a7d72 100644 --- a/src/quick/items/qquickanimatedimage.cpp +++ b/src/quick/items/qquickanimatedimage.cpp @@ -426,15 +426,18 @@ void QQuickAnimatedImage::movieRequestFinished() } bool pausedAtStart = d->paused; - if (d->playing) + if (d->movie && d->playing) d->movie->start(); - if (pausedAtStart) + if (d->movie && pausedAtStart) d->movie->setPaused(true); - if (d->paused || !d->playing) { + if (d->movie && (d->paused || !d->playing)) { d->movie->jumpToFrame(d->presetCurrentFrame); d->presetCurrentFrame = 0; } - d->setPixmap(*d->infoForCurrentFrame(qmlEngine(this))); + + QQuickPixmap *pixmap = d->infoForCurrentFrame(qmlEngine(this)); + if (pixmap) + d->setPixmap(*pixmap); if (isPlaying() != d->oldPlaying) emit playingChanged(); @@ -512,7 +515,10 @@ void QQuickAnimatedImagePrivate::setMovie(QMovie *m) Q_Q(QQuickAnimatedImage); const int oldFrameCount = q->frameCount(); - delete movie; + if (movie) { + movie->disconnect(); + movie->deleteLater(); + } movie = m; if (oldFrameCount != q->frameCount()) diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp index 190c48ac88..887c30f999 100644 --- a/src/quick/items/qquickanimatedsprite.cpp +++ b/src/quick/items/qquickanimatedsprite.cpp @@ -527,6 +527,8 @@ void QQuickAnimatedSprite::setSource(QUrl arg) Q_D(QQuickAnimatedSprite); if (d->m_sprite->m_source != arg) { + const qreal targetDevicePixelRatio = (window() ? window()->effectiveDevicePixelRatio() : qApp->devicePixelRatio()); + d->m_sprite->setDevicePixelRatio(targetDevicePixelRatio); d->m_sprite->setSource(arg); Q_EMIT sourceChanged(arg); reloadImage(); @@ -713,7 +715,7 @@ QSGSpriteNode* QQuickAnimatedSprite::initNode() QSGSpriteNode *node = d->sceneGraphContext()->createSpriteNode(); - d->m_sheetSize = QSize(image.size()); + d->m_sheetSize = QSize(image.size() / image.devicePixelRatioF()); node->setTexture(window()->createTextureFromImage(image)); d->m_spriteEngine->start(0); node->setTime(0.0f); diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 1be4bafe28..d020ad7c4c 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -849,14 +849,16 @@ void QQuickEventPoint::setGrabberItem(QQuickItem *grabber) qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << hex << m_pointId << pointStateString(this) << ": grab" << m_exclusiveGrabber << "->" << grabber; } + QQuickItem *oldGrabberItem = grabberItem(); m_exclusiveGrabber = QPointer<QObject>(grabber); m_grabberIsHandler = false; m_sceneGrabPos = m_scenePos; - QQuickItem *oldGrabberItem = grabberItem(); - if (oldGrabberHandler) + if (oldGrabberHandler) { oldGrabberHandler->onGrabChanged(oldGrabberHandler, (grabber ? CancelGrabExclusive : UngrabExclusive), this); - else if (oldGrabberItem && oldGrabberItem != grabber && grabber && pointerEvent()->asPointerTouchEvent()) - oldGrabberItem->touchUngrabEvent(); + } else if (oldGrabberItem && oldGrabberItem != grabber && grabber && grabber->window()) { + QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(grabber->window()); + windowPriv->sendUngrabEvent(oldGrabberItem, windowPriv->isDeliveringTouchAsMouse()); + } for (QPointer<QQuickPointerHandler> passiveGrabber : m_passiveGrabbers) passiveGrabber->onGrabChanged(passiveGrabber, OverrideGrabPassive, this); } @@ -1388,6 +1390,7 @@ void QQuickPointerTouchEvent::localize(QQuickItem *target) point->localizePosition(target); } +#if QT_CONFIG(gestures) QQuickPointerEvent *QQuickPointerNativeGestureEvent::reset(QEvent *event) { auto ev = static_cast<QNativeGestureEvent*>(event); @@ -1417,6 +1420,7 @@ void QQuickPointerNativeGestureEvent::localize(QQuickItem *target) { m_gesturePoint->localizePosition(target); } +#endif // QT_CONFIG(gestures) QQuickEventPoint *QQuickPointerMouseEvent::point(int i) const { if (i == 0) @@ -1430,11 +1434,13 @@ QQuickEventPoint *QQuickPointerTouchEvent::point(int i) const { return nullptr; } +#if QT_CONFIG(gestures) QQuickEventPoint *QQuickPointerNativeGestureEvent::point(int i) const { if (i == 0) return m_gesturePoint; return nullptr; } +#endif // QT_CONFIG(gestures) QQuickEventPoint::QQuickEventPoint(QQuickPointerEvent *parent) : QObject(parent), m_pointId(0), m_exclusiveGrabber(nullptr), m_timestamp(0), m_pressTimestamp(0), @@ -1572,6 +1578,13 @@ void QQuickPointerTouchEvent::clearGrabbers() const { } } +Qt::TouchPointStates QQuickPointerTouchEvent::touchPointStates() const +{ + return m_event + ? static_cast<QTouchEvent*>(m_event)->touchPointStates() + : Qt::TouchPointStates(); +} + /*! Returns whether the given \a handler is the exclusive grabber of any touchpoint within this event. @@ -1586,17 +1599,17 @@ bool QQuickPointerTouchEvent::hasExclusiveGrabber(const QQuickPointerHandler *ha bool QQuickPointerTouchEvent::isPressEvent() const { - return static_cast<QTouchEvent*>(m_event)->touchPointStates() & Qt::TouchPointPressed; + return touchPointStates() & Qt::TouchPointPressed; } bool QQuickPointerTouchEvent::isUpdateEvent() const { - return static_cast<QTouchEvent*>(m_event)->touchPointStates() & (Qt::TouchPointMoved | Qt::TouchPointStationary); + return touchPointStates() & (Qt::TouchPointMoved | Qt::TouchPointStationary); } bool QQuickPointerTouchEvent::isReleaseEvent() const { - return static_cast<QTouchEvent*>(m_event)->touchPointStates() & Qt::TouchPointReleased; + return touchPointStates() & Qt::TouchPointReleased; } QVector<QPointF> QQuickPointerEvent::unacceptedPressedPointScenePositions() const @@ -1655,6 +1668,7 @@ QMouseEvent *QQuickPointerTouchEvent::syntheticMouseEvent(int pointID, QQuickIte return &m_synthMouseEvent; } +#if QT_CONFIG(gestures) /*! Returns the exclusive grabber of this event, if any, in a vector. */ @@ -1712,6 +1726,7 @@ qreal QQuickPointerNativeGestureEvent::value() const { return static_cast<QNativeGestureEvent *>(m_event)->value(); } +#endif // QT_CONFIG(gestures) /*! \internal @@ -1735,12 +1750,13 @@ QQuickEventPoint *QQuickPointerTouchEvent::pointById(int pointId) const { return nullptr; } +#if QT_CONFIG(gestures) QQuickEventPoint *QQuickPointerNativeGestureEvent::pointById(int pointId) const { if (m_gesturePoint && pointId == m_gesturePoint->pointId()) return m_gesturePoint; return nullptr; } - +#endif /*! \internal @@ -1859,6 +1875,7 @@ QTouchEvent *QQuickPointerTouchEvent::asTouchEvent() const return static_cast<QTouchEvent *>(m_event); } +#if QT_CONFIG(gestures) bool QQuickPointerNativeGestureEvent::allPointsAccepted() const { return m_gesturePoint->isAccepted(); } @@ -1871,6 +1888,7 @@ bool QQuickPointerNativeGestureEvent::allPointsGrabbed() const { return m_gesturePoint->exclusiveGrabber() != nullptr; } +#endif // QT_CONFIG(gestures) #ifndef QT_NO_DEBUG_STREAM diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h index 2a1e9dc184..bb6726706d 100644 --- a/src/quick/items/qquickevents_p_p.h +++ b/src/quick/items/qquickevents_p_p.h @@ -66,7 +66,9 @@ QT_BEGIN_NAMESPACE class QQuickPointerDevice; class QQuickPointerEvent; class QQuickPointerMouseEvent; +#if QT_CONFIG(gestures) class QQuickPointerNativeGestureEvent; +#endif class QQuickPointerTabletEvent; class QQuickPointerTouchEvent; class QQuickPointerHandler; @@ -414,11 +416,15 @@ public: // helpers for C++ only (during event delivery) virtual QQuickPointerMouseEvent *asPointerMouseEvent() { return nullptr; } virtual QQuickPointerTouchEvent *asPointerTouchEvent() { return nullptr; } virtual QQuickPointerTabletEvent *asPointerTabletEvent() { return nullptr; } +#if QT_CONFIG(gestures) virtual QQuickPointerNativeGestureEvent *asPointerNativeGestureEvent() { return nullptr; } +#endif virtual const QQuickPointerMouseEvent *asPointerMouseEvent() const { return nullptr; } virtual const QQuickPointerTouchEvent *asPointerTouchEvent() const { return nullptr; } virtual const QQuickPointerTabletEvent *asPointerTabletEvent() const { return nullptr; } +#if QT_CONFIG(gestures) virtual const QQuickPointerNativeGestureEvent *asPointerNativeGestureEvent() const { return nullptr; } +#endif virtual bool allPointsAccepted() const = 0; virtual bool allUpdatedPointsAccepted() const = 0; virtual bool allPointsGrabbed() const = 0; @@ -510,6 +516,8 @@ public: QTouchEvent *asTouchEvent() const; private: + Qt::TouchPointStates touchPointStates() const; + int m_pointCount = 0; QVector<QQuickEventTouchPoint *> m_touchPoints; mutable QMouseEvent m_synthMouseEvent; @@ -517,6 +525,7 @@ private: Q_DISABLE_COPY(QQuickPointerTouchEvent) }; +#if QT_CONFIG(gestures) class Q_QUICK_PRIVATE_EXPORT QQuickPointerNativeGestureEvent : public QQuickPointerEvent { Q_OBJECT @@ -551,6 +560,7 @@ private: Q_DISABLE_COPY(QQuickPointerNativeGestureEvent) }; +#endif // QT_CONFIG(gestures) // ### Qt 6: move this to qtbase, replace QTouchDevice and the enums in QTabletEvent diff --git a/src/quick/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h index eb04a1d162..d8d0be9b8c 100644 --- a/src/quick/items/qquickimagebase_p.h +++ b/src/quick/items/qquickimagebase_p.h @@ -98,7 +98,7 @@ public: virtual void setAutoTransform(bool transform); bool autoTransform() const; - void resolve2xLocalFile(const QUrl &url, qreal targetDevicePixelRatio, QUrl *sourceUrl, qreal *sourceDevicePixelRatio); + static void resolve2xLocalFile(const QUrl &url, qreal targetDevicePixelRatio, QUrl *sourceUrl, qreal *sourceDevicePixelRatio); // Use a virtual rather than a signal->signal to avoid the huge // connect/conneciton overhead for this rare case. diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 3a0aea517c..70bb7db2b0 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -3134,6 +3134,9 @@ void QQuickItemPrivate::itemToParentTransform(QTransform &t) const */ QTransform QQuickItemPrivate::windowToGlobalTransform() const { + if (Q_UNLIKELY(window == nullptr)) + return QTransform(); + QPoint quickWidgetOffset; QWindow *renderWindow = QQuickRenderControl::renderWindowFor(window, &quickWidgetOffset); QPointF pos = (renderWindow ? renderWindow : window)->mapToGlobal(quickWidgetOffset); @@ -3145,6 +3148,9 @@ QTransform QQuickItemPrivate::windowToGlobalTransform() const */ QTransform QQuickItemPrivate::globalToWindowTransform() const { + if (Q_UNLIKELY(window == nullptr)) + return QTransform(); + QPoint quickWidgetOffset; QWindow *renderWindow = QQuickRenderControl::renderWindowFor(window, &quickWidgetOffset); QPointF pos = (renderWindow ? renderWindow : window)->mapToGlobal(quickWidgetOffset); @@ -7456,11 +7462,8 @@ void QQuickItem::grabMouse() auto point = fromTouch ? windowPriv->pointerEventInstance(windowPriv->touchMouseDevice)->pointById(windowPriv->touchMouseId) : windowPriv->pointerEventInstance(QQuickPointerDevice::genericMouseDevice())->point(0); - if (point) { - QQuickItem *oldGrabber = point->grabberItem(); + if (point) point->setGrabberItem(this); - windowPriv->sendUngrabEvent(oldGrabber, fromTouch); - } } /*! diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 33becd71ec..60f7efae12 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -538,8 +538,13 @@ FxViewItem *QQuickListViewPrivate::snapItemAt(qreal pos) qreal itemTop = item->position(); if (highlight && itemTop >= pos && item->endPosition() <= pos + highlight->size()) return item; - if (itemTop+item->size()/2 >= pos && itemTop-prevItemSize/2 < pos) + + // Middle of item and spacing (i.e. the middle of the distance between this item and the next + qreal halfwayToNextItem = itemTop + (item->size()+spacing) / 2; + qreal halfwayToPrevItem = itemTop - (prevItemSize+spacing) / 2; + if (halfwayToNextItem >= pos && halfwayToPrevItem < pos) snapItem = item; + prevItemSize = item->size(); } return snapItem; diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index 052da9fe82..c9316c0406 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -910,7 +910,7 @@ void QQuickMouseArea::ungrabMouse() if (d->pressed) { // if our mouse grab has been removed (probably by Flickable), fix our // state - d->pressed = nullptr; + d->pressed = Qt::NoButton; d->stealMouse = false; d->doubleClick = false; d->overThreshold = false; diff --git a/src/quick/items/qquicksprite.cpp b/src/quick/items/qquicksprite.cpp index 6b8567439b..8c59a68982 100644 --- a/src/quick/items/qquicksprite.cpp +++ b/src/quick/items/qquicksprite.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qquicksprite_p.h" +#include "qquickimagebase_p.h" #include <qqml.h> #include <QDebug> #include <QRandomGenerator> @@ -222,6 +223,7 @@ QQuickSprite::QQuickSprite(QObject *parent) , m_frameDuration(unsetDuration) , m_frameDurationVariation(0) , m_frameSync(false) + , m_devicePixelRatio(1.0) { } @@ -265,7 +267,10 @@ void QQuickSprite::startImageLoading() if (!e) qWarning() << "QQuickSprite: Cannot find QQmlEngine - this class is only for use in QML and may not work"; } - m_pix.load(e, m_source); + QUrl loadUrl = m_source; + QQuickImageBase::resolve2xLocalFile(m_source, m_devicePixelRatio, &loadUrl, &m_devicePixelRatio); + + m_pix.load(e, loadUrl); } } diff --git a/src/quick/items/qquicksprite_p.h b/src/quick/items/qquicksprite_p.h index 8e119a80a9..fab9e75190 100644 --- a/src/quick/items/qquicksprite_p.h +++ b/src/quick/items/qquicksprite_p.h @@ -168,6 +168,16 @@ public: return m_frameSync; } + void setDevicePixelRatio(qreal dpr) + { + m_devicePixelRatio = dpr; + } + + qreal devicePixelRatio() const + { + return m_devicePixelRatio; + } + Q_SIGNALS: void sourceChanged(QUrl arg); @@ -308,6 +318,7 @@ private: friend class QQuickAnimatedSprite; friend class QQuickSpriteEngine; friend class QQuickStochasticEngine; + int m_generatedCount; int m_framesPerRow; int m_rowY; @@ -325,6 +336,7 @@ private: int m_frameDuration; int m_frameDurationVariation; bool m_frameSync; + qreal m_devicePixelRatio; QQuickPixmap m_pix; }; diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp index 1fd15e61e3..be297bbe76 100644 --- a/src/quick/items/qquickspriteengine.cpp +++ b/src/quick/items/qquickspriteengine.cpp @@ -390,6 +390,7 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) int w = 0; m_maxFrames = 0; m_imageStateCount = 0; + qreal pixelRatio = 1.0; for (QQuickSprite* state : qAsConst(m_sprites)) { if (state->frames() > m_maxFrames) @@ -413,6 +414,8 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) if (!state->m_frameHeight) state->m_frameHeight = img.height(); + pixelRatio = qMax(pixelRatio, state->devicePixelRatio()); + if (state->frames() * state->frameWidth() > maxSize){ struct helper{ static int divRoundUp(int a, int b){return (a+b-1)/b;} @@ -437,43 +440,58 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) } } + if (h > maxSize){ + qWarning() << "SpriteEngine: Too many animations to fit in one texture..."; + qWarning() << "SpriteEngine: Your texture max size today is " << maxSize; + return QImage(); + } + //maxFrames is max number in a line of the texture - QImage image(w, h, QImage::Format_ARGB32_Premultiplied); + QImage image(w * pixelRatio, h * pixelRatio, QImage::Format_ARGB32_Premultiplied); + image.setDevicePixelRatio(pixelRatio); image.fill(0); QPainter p(&image); int y = 0; for (QQuickSprite* state : qAsConst(m_sprites)) { QImage img(state->m_pix.image()); - int frameWidth = state->m_frameWidth; - int frameHeight = state->m_frameHeight; - if (img.height() == frameHeight && img.width() < maxSize){//Simple case - p.drawImage(0,y,img.copy(state->m_frameX,0,state->m_frames * frameWidth, frameHeight)); + const int frameWidth = state->m_frameWidth; + const int frameHeight = state->m_frameHeight; + const int imgHeight = img.height() / img.devicePixelRatioF(); + const int imgWidth = img.width() / img.devicePixelRatioF(); + if (imgHeight == frameHeight && imgWidth < maxSize){ //Simple case + p.drawImage(QRect(0, y, state->m_frames * frameWidth, frameHeight), + img, + QRect(state->m_frameX * img.devicePixelRatioF(), 0, state->m_frames * frameWidth * img.devicePixelRatioF(), frameHeight * img.devicePixelRatioF())); state->m_rowStartX = 0; state->m_rowY = y; y += frameHeight; - }else{//Chopping up image case - state->m_framesPerRow = image.width()/frameWidth; + } else { //Chopping up image case + state->m_framesPerRow = w/frameWidth; state->m_rowY = y; int x = 0; int curX = state->m_frameX; int curY = state->m_frameY; int framesLeft = state->frames(); while (framesLeft > 0){ - if (image.width() - x + curX <= img.width()){//finish a row in image (dest) - int copied = image.width() - x; + if (w - x + curX <= imgWidth){//finish a row in image (dest) + int copied = w - x; framesLeft -= copied/frameWidth; - p.drawImage(x,y,img.copy(curX,curY,copied,frameHeight)); + p.drawImage(QRect(x, y, copied, frameHeight), + img, + QRect(curX * img.devicePixelRatioF(), curY * img.devicePixelRatioF(), copied * img.devicePixelRatioF(), frameHeight * img.devicePixelRatioF())); y += frameHeight; curX += copied; x = 0; - if (curX == img.width()){ + if (curX == imgWidth){ curX = 0; curY += frameHeight; } }else{//finish a row in img (src) - int copied = img.width() - curX; + int copied = imgWidth - curX; framesLeft -= copied/frameWidth; - p.drawImage(x,y,img.copy(curX,curY,copied,frameHeight)); + p.drawImage(QRect(x, y, copied, frameHeight), + img, + QRect(curX * img.devicePixelRatioF(), curY * img.devicePixelRatioF(), copied * img.devicePixelRatioF(), frameHeight * img.devicePixelRatioF())); curY += frameHeight; x += copied; curX = 0; @@ -484,12 +502,6 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) } } - if (image.height() > maxSize){ - qWarning() << "SpriteEngine: Too many animations to fit in one texture..."; - qWarning() << "SpriteEngine: Your texture max size today is " << maxSize; - return QImage(); - } - #ifdef SPRITE_IMAGE_DEBUG QString fPath = QDir::tempPath() + "/SpriteImage.%1.png"; int acc = 0; diff --git a/src/quick/items/qquickspritesequence.cpp b/src/quick/items/qquickspritesequence.cpp index 72761ab82b..df6a6e336e 100644 --- a/src/quick/items/qquickspritesequence.cpp +++ b/src/quick/items/qquickspritesequence.cpp @@ -226,7 +226,7 @@ QSGSpriteNode *QQuickSpriteSequence::initNode() QSGSpriteNode *node = d->sceneGraphContext()->createSpriteNode(); - d->m_sheetSize = QSize(image.size()); + d->m_sheetSize = QSize(image.size() / image.devicePixelRatioF()); node->setTexture(window()->createTextureFromImage(image)); d->m_spriteEngine->start(0); node->setTime(0.0f); diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp index e3080dfe48..1cb12235c1 100644 --- a/src/quick/items/qquicktextcontrol.cpp +++ b/src/quick/items/qquicktextcontrol.cpp @@ -1304,8 +1304,12 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) cursor.removeSelectedText(); } + QTextBlock block; + // insert commit string if (!e->commitString().isEmpty() || e->replacementLength()) { + if (e->commitString().endsWith(QChar::LineFeed)) + block = cursor.block(); // Remember the block where the preedit text is QTextCursor c = cursor; c.setPosition(c.position() + e->replacementStart()); c.setPosition(c.position() + e->replacementLength(), QTextCursor::KeepAnchor); @@ -1324,7 +1328,9 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) } } - QTextBlock block = cursor.block(); + if (!block.isValid()) + block = cursor.block(); + QTextLayout *layout = block.layout(); if (isGettingInput) { layout->setPreeditArea(cursor.position() - block.position(), e->preeditString()); diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 02fe4809ab..fb81a835e9 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -2227,8 +2227,10 @@ QQuickPointerEvent *QQuickWindowPrivate::queryPointerEventInstance(QQuickPointer for (QQuickPointerEvent *e : pointerEventInstances) { // If device can generate native gestures (e.g. a trackpad), there might be two QQuickPointerEvents: // QQuickPointerNativeGestureEvent and QQuickPointerTouchEvent. Use eventType to disambiguate. +#if QT_CONFIG(gestures) if (eventType == QEvent::NativeGesture && !qobject_cast<QQuickPointerNativeGestureEvent*>(e)) continue; +#endif // Otherwise we assume there's only one event type per device. // More disambiguation tests might need to be added above if that changes later. if (e->device() == device) @@ -2252,9 +2254,11 @@ QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QQuickPointerDevic break; case QQuickPointerDevice::TouchPad: case QQuickPointerDevice::TouchScreen: +#if QT_CONFIG(gestures) if (eventType == QEvent::NativeGesture) ev = new QQuickPointerNativeGestureEvent(q, device); else // assume QEvent::Type is one of TouchBegin/Update/End +#endif ev = new QQuickPointerTouchEvent(q, device); break; default: @@ -2289,9 +2293,11 @@ QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QEvent *event) con dev = QQuickPointerDevice::touchDevice(static_cast<QTouchEvent *>(event)->device()); break; // TODO tablet event types +#if QT_CONFIG(gestures) case QEvent::NativeGesture: dev = QQuickPointerDevice::touchDevice(static_cast<QNativeGestureEvent *>(event)->device()); break; +#endif default: break; } @@ -2313,8 +2319,9 @@ void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event) deliverMouseEvent(event->asPointerMouseEvent()); // failsafe: never allow any kind of grab to persist after release if (event->isReleaseEvent() && event->buttons() == Qt::NoButton) { + QQuickItem *oldGrabber = q->mouseGrabberItem(); event->clearGrabbers(); - sendUngrabEvent(q->mouseGrabberItem(), false); + sendUngrabEvent(oldGrabber, false); } } else if (event->asPointerTouchEvent()) { deliverTouchEvent(event->asPointerTouchEvent()); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp index aa83709b72..74426c5c4d 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp @@ -68,6 +68,9 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin QMargins sourceMargins = normalizedMargins(sourceMarginsIn); QMargins targetMargins = normalizedMargins(targetMarginsIn); + const qreal sourceDpr = pixmap.devicePixelRatioF(); + sourceMargins *= sourceDpr; + // source center const int sourceCenterTop = sourceRect.top() + sourceMargins.top(); const int sourceCenterLeft = sourceRect.left() + sourceMargins.left(); @@ -89,9 +92,9 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin int columns = 3; int rows = 3; if (rules.horizontal != Qt::StretchTile && sourceCenterWidth != 0) - columns = qMax(3, 2 + qCeil(targetCenterWidth / qreal(sourceCenterWidth))); + columns = qMax(3, 2 + qCeil((targetCenterWidth * sourceDpr) / qreal(sourceCenterWidth))); if (rules.vertical != Qt::StretchTile && sourceCenterHeight != 0) - rows = qMax(3, 2 + qCeil(targetCenterHeight / qreal(sourceCenterHeight))); + rows = qMax(3, 2 + qCeil((targetCenterHeight * sourceDpr) / qreal(sourceCenterHeight))); xTarget.resize(columns + 1); yTarget.resize(rows + 1); @@ -121,7 +124,7 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin dx = targetCenterWidth; break; case Qt::RepeatTile: - dx = sourceCenterWidth; + dx = sourceCenterWidth / sourceDpr; break; case Qt::RoundTile: dx = targetCenterWidth / qreal(columns - 2); @@ -136,7 +139,7 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin dy = targetCenterHeight; break; case Qt::RepeatTile: - dy = sourceCenterHeight; + dy = sourceCenterHeight / sourceDpr; break; case Qt::RoundTile: dy = targetCenterHeight / qreal(rows - 2); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp index ba7bbc2d11..d4e5e98d68 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp @@ -123,7 +123,7 @@ void QSGSoftwareSpriteNode::paint(QPainter *painter) // XXX try to do some kind of interpolation between sourceA and sourceB using time painter->drawPixmap(QRectF(0, 0, m_size.width(), m_size.height()), pixmap, - QRectF(m_sourceA, m_spriteSize)); + QRectF(m_sourceA * pixmap.devicePixelRatioF(), m_spriteSize * pixmap.devicePixelRatioF())); } bool QSGSoftwareSpriteNode::isOpaque() const diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index ba71551302..afe3380494 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -775,9 +775,7 @@ Renderer::Renderer(QSGDefaultRenderContext *ctx) , m_currentClip(nullptr) , m_currentClipType(NoClip) , m_vertexUploadPool(256) -#ifdef QSG_SEPARATE_INDEX_BUFFER , m_indexUploadPool(64) -#endif , m_vao(nullptr) , m_visualizeMode(VisualizeNothing) { @@ -834,12 +832,11 @@ static void qsg_wipeBuffer(Buffer *buffer, QOpenGLFunctions *funcs) free(buffer->data); } -static void qsg_wipeBatch(Batch *batch, QOpenGLFunctions *funcs) +static void qsg_wipeBatch(Batch *batch, QOpenGLFunctions *funcs, bool separateIndexBuffer) { qsg_wipeBuffer(&batch->vbo, funcs); -#ifdef QSG_SEPARATE_INDEX_BUFFER - qsg_wipeBuffer(&batch->ibo, funcs); -#endif + if (separateIndexBuffer) + qsg_wipeBuffer(&batch->ibo, funcs); delete batch; } @@ -847,9 +844,13 @@ Renderer::~Renderer() { if (QOpenGLContext::currentContext()) { // Clean up batches and buffers - for (int i=0; i<m_opaqueBatches.size(); ++i) qsg_wipeBatch(m_opaqueBatches.at(i), this); - for (int i=0; i<m_alphaBatches.size(); ++i) qsg_wipeBatch(m_alphaBatches.at(i), this); - for (int i=0; i<m_batchPool.size(); ++i) qsg_wipeBatch(m_batchPool.at(i), this); + const bool separateIndexBuffer = m_context->separateIndexBuffer(); + for (int i = 0; i < m_opaqueBatches.size(); ++i) + qsg_wipeBatch(m_opaqueBatches.at(i), this, separateIndexBuffer); + for (int i = 0; i < m_alphaBatches.size(); ++i) + qsg_wipeBatch(m_alphaBatches.at(i), this, separateIndexBuffer); + for (int i = 0; i < m_batchPool.size(); ++i) + qsg_wipeBatch(m_batchPool.at(i), this, separateIndexBuffer); } for (Node *n : qAsConst(m_nodes)) @@ -889,13 +890,8 @@ void Renderer::map(Buffer *buffer, int byteSize, bool isIndexBuf) if (!m_context->hasBrokenIndexBufferObjects() && m_visualizeMode == VisualizeNothing) { // Common case, use a shared memory pool for uploading vertex data to avoid // excessive reevaluation - QDataBuffer<char> &pool = -#ifdef QSG_SEPARATE_INDEX_BUFFER - isIndexBuf ? m_indexUploadPool : m_vertexUploadPool; -#else - m_vertexUploadPool; - Q_UNUSED(isIndexBuf); -#endif + QDataBuffer<char> &pool = m_context->separateIndexBuffer() && isIndexBuf + ? m_indexUploadPool : m_vertexUploadPool; if (byteSize > pool.size()) pool.resize(byteSize); buffer->data = pool.data(); @@ -1864,11 +1860,11 @@ void Renderer::uploadBatch(Batch *b) ibufferSize = unmergedIndexSize; } -#ifdef QSG_SEPARATE_INDEX_BUFFER - map(&b->ibo, ibufferSize, true); -#else - bufferSize += ibufferSize; -#endif + const bool separateIndexBuffer = m_context->separateIndexBuffer(); + if (separateIndexBuffer) + map(&b->ibo, ibufferSize, true); + else + bufferSize += ibufferSize; map(&b->vbo, bufferSize); if (Q_UNLIKELY(debug_upload())) qDebug() << " - batch" << b << " first:" << b->first << " root:" @@ -1878,22 +1874,17 @@ void Renderer::uploadBatch(Batch *b) if (b->merged) { char *vertexData = b->vbo.data; char *zData = vertexData + b->vertexCount * g->sizeOfVertex(); -#ifdef QSG_SEPARATE_INDEX_BUFFER - char *indexData = b->ibo.data; -#else - char *indexData = zData + (m_useDepthBuffer ? b->vertexCount * sizeof(float) : 0); -#endif + char *indexData = separateIndexBuffer + ? b->ibo.data + : zData + (int(m_useDepthBuffer) * b->vertexCount * sizeof(float)); quint16 iOffset = 0; e = b->first; int verticesInSet = 0; int indicesInSet = 0; b->drawSets.reset(); -#ifdef QSG_SEPARATE_INDEX_BUFFER - int drawSetIndices = 0; -#else - int drawSetIndices = indexData - vertexData; -#endif + int drawSetIndices = separateIndexBuffer ? 0 : indexData - vertexData; + const auto indexBase = separateIndexBuffer ? b->ibo.data : b->vbo.data; b->drawSets << DrawSet(0, zData - vertexData, drawSetIndices); while (e) { verticesInSet += e->node->geometry()->vertexCount(); @@ -1903,11 +1894,7 @@ void Renderer::uploadBatch(Batch *b) b->drawSets.last().indices += 1 * sizeof(quint16); b->drawSets.last().indexCount -= 2; } -#ifdef QSG_SEPARATE_INDEX_BUFFER - drawSetIndices = indexData - b->ibo.data; -#else - drawSetIndices = indexData - b->vbo.data; -#endif + drawSetIndices = indexData - indexBase; b->drawSets << DrawSet(vertexData - b->vbo.data, zData - b->vbo.data, drawSetIndices); @@ -1927,11 +1914,8 @@ void Renderer::uploadBatch(Batch *b) } } else { char *vboData = b->vbo.data; -#ifdef QSG_SEPARATE_INDEX_BUFFER - char *iboData = b->ibo.data; -#else - char *iboData = vboData + b->vertexCount * g->sizeOfVertex(); -#endif + char *iboData = separateIndexBuffer ? b->ibo.data + : vboData + b->vertexCount * g->sizeOfVertex(); Element *e = b->first; while (e) { QSGGeometry *g = e->node->geometry(); @@ -1979,12 +1963,9 @@ void Renderer::uploadBatch(Batch *b) } if (!b->drawSets.isEmpty()) { - const quint16 *id = -# ifdef QSG_SEPARATE_INDEX_BUFFER - (const quint16 *) (b->ibo.data); -# else - (const quint16 *) (b->vbo.data + b->drawSets.at(0).indices); -# endif + const quint16 *id = (const quint16 *)(separateIndexBuffer + ? b->ibo.data + : b->vbo.data + b->drawSets.at(0).indices); { QDebug iDump = qDebug(); iDump << " -- Index Data, count:" << b->indexCount; @@ -2004,9 +1985,8 @@ void Renderer::uploadBatch(Batch *b) #endif // QT_NO_DEBUG_OUTPUT unmap(&b->vbo); -#ifdef QSG_SEPARATE_INDEX_BUFFER - unmap(&b->ibo, true); -#endif + if (separateIndexBuffer) + unmap(&b->ibo, true); if (Q_UNLIKELY(debug_upload())) qDebug() << " --- vertex/index buffers unmapped, batch upload completed..."; @@ -2299,11 +2279,7 @@ void Renderer::renderMergedBatch(const Batch *batch) glBindBuffer(GL_ARRAY_BUFFER, batch->vbo.id); char *indexBase = nullptr; -#ifdef QSG_SEPARATE_INDEX_BUFFER - const Buffer *indexBuf = &batch->ibo; -#else - const Buffer *indexBuf = &batch->vbo; -#endif + const Buffer *indexBuf = m_context->separateIndexBuffer() ? &batch->ibo : &batch->vbo; if (m_context->hasBrokenIndexBufferObjects()) { indexBase = indexBuf->data; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -2395,11 +2371,8 @@ void Renderer::renderUnmergedBatch(const Batch *batch) glBindBuffer(GL_ARRAY_BUFFER, batch->vbo.id); char *indexBase = nullptr; -#ifdef QSG_SEPARATE_INDEX_BUFFER - const Buffer *indexBuf = &batch->ibo; -#else - const Buffer *indexBuf = &batch->vbo; -#endif + const auto separateIndexBuffer = m_context->separateIndexBuffer(); + const Buffer *indexBuf = separateIndexBuffer ? &batch->ibo : &batch->vbo; if (batch->indexCount) { if (m_context->hasBrokenIndexBufferObjects()) { indexBase = indexBuf->data; @@ -2428,11 +2401,9 @@ void Renderer::renderUnmergedBatch(const Batch *batch) } int vOffset = 0; -#ifdef QSG_SEPARATE_INDEX_BUFFER char *iOffset = indexBase; -#else - char *iOffset = indexBase + batch->vertexCount * gn->geometry()->sizeOfVertex(); -#endif + if (!separateIndexBuffer) + iOffset += batch->vertexCount * gn->geometry()->sizeOfVertex(); QMatrix4x4 rootMatrix = batch->root ? qsg_matrixForRoot(batch->root) : QMatrix4x4(); @@ -2735,17 +2706,13 @@ void Renderer::render() if (Q_UNLIKELY(debug_render())) timeSorting = timer.restart(); int largestVBO = 0; -#ifdef QSG_SEPARATE_INDEX_BUFFER int largestIBO = 0; -#endif if (Q_UNLIKELY(debug_upload())) qDebug("Uploading Opaque Batches:"); for (int i=0; i<m_opaqueBatches.size(); ++i) { Batch *b = m_opaqueBatches.at(i); largestVBO = qMax(b->vbo.size, largestVBO); -#ifdef QSG_SEPARATE_INDEX_BUFFER largestIBO = qMax(b->ibo.size, largestIBO); -#endif uploadBatch(b); } if (Q_UNLIKELY(debug_render())) timeUploadOpaque = timer.restart(); @@ -2756,18 +2723,14 @@ void Renderer::render() Batch *b = m_alphaBatches.at(i); uploadBatch(b); largestVBO = qMax(b->vbo.size, largestVBO); -#ifdef QSG_SEPARATE_INDEX_BUFFER largestIBO = qMax(b->ibo.size, largestIBO); -#endif } if (Q_UNLIKELY(debug_render())) timeUploadAlpha = timer.restart(); if (largestVBO * 2 < m_vertexUploadPool.size()) m_vertexUploadPool.resize(largestVBO * 2); -#ifdef QSG_SEPARATE_INDEX_BUFFER - if (largestIBO * 2 < m_indexUploadPool.size()) + if (m_context->separateIndexBuffer() && largestIBO * 2 < m_indexUploadPool.size()) m_indexUploadPool.resize(largestIBO * 2); -#endif renderBatches(); @@ -2978,14 +2941,12 @@ void Renderer::visualizeBatch(Batch *b) if (b->merged) { shader->setUniformValue(shader->matrix, matrix); + const auto &dataStart = m_context->separateIndexBuffer() ? b->ibo.data : b->vbo.data; for (int ds=0; ds<b->drawSets.size(); ++ds) { const DrawSet &set = b->drawSets.at(ds); glVertexAttribPointer(a.position, 2, a.type, false, g->sizeOfVertex(), (void *) (qintptr) (set.vertices)); -#ifdef QSG_SEPARATE_INDEX_BUFFER - glDrawElements(g->drawingMode(), set.indexCount, GL_UNSIGNED_SHORT, (void *) (qintptr) (b->ibo.data + set.indices)); -#else - glDrawElements(g->drawingMode(), set.indexCount, GL_UNSIGNED_SHORT, (void *) (qintptr) (b->vbo.data + set.indices)); -#endif + glDrawElements(g->drawingMode(), set.indexCount, GL_UNSIGNED_SHORT, + (void *)(qintptr)(dataStart + set.indices)); } } else { Element *e = b->first; diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index 918f3ce82c..12b48c1451 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -433,9 +433,7 @@ struct Batch mutable uint uploadedThisFrame : 1; // solely for debugging purposes Buffer vbo; -#ifdef QSG_SEPARATE_INDEX_BUFFER Buffer ibo; -#endif QDataBuffer<DrawSet> drawSets; }; @@ -738,9 +736,7 @@ private: ClipType m_currentClipType; QDataBuffer<char> m_vertexUploadPool; -#ifdef QSG_SEPARATE_INDEX_BUFFER QDataBuffer<char> m_indexUploadPool; -#endif // For minimal OpenGL core profile support QOpenGLVertexArrayObject *m_vao; @@ -760,10 +756,8 @@ Batch *Renderer::newBatch() m_batchPool.resize(size - 1); } else { b = new Batch(); - memset(&b->vbo, 0, sizeof(Buffer)); -#ifdef QSG_SEPARATE_INDEX_BUFFER - memset(&b->ibo, 0, sizeof(Buffer)); -#endif + Q_ASSERT(offsetof(Batch, ibo) == sizeof(Buffer) + offsetof(Batch, vbo)); + memset(&b->vbo, 0, sizeof(Buffer) * 2); // Clear VBO & IBO } b->init(); return b; diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp index 7882496062..22e97a2dc9 100644 --- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp +++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp @@ -39,6 +39,7 @@ #include "qsgdefaultrendercontext_p.h" +#include <QtGui/QGuiApplication> #include <QtGui/QOpenGLFramebufferObject> #include <QtQuick/private/qsgbatchrenderer_p.h> @@ -317,6 +318,17 @@ QSGDefaultRenderContext *QSGDefaultRenderContext::from(QOpenGLContext *context) return qobject_cast<QSGDefaultRenderContext *>(context->property(QSG_RENDERCONTEXT_PROPERTY).value<QObject *>()); } +bool QSGDefaultRenderContext::separateIndexBuffer() const +{ + // WebGL: A given WebGLBuffer object may only be bound to one of + // the ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER target in its + // lifetime. An attempt to bind a buffer object to the other + // target will generate an INVALID_OPERATION error, and the + // current binding will remain untouched. + static const bool isWebGL = qGuiApp->platformName().compare(QLatin1String("webgl")) == 0; + return isWebGL; +} + QSGDistanceFieldGlyphCache *QSGDefaultRenderContext::distanceFieldGlyphCache(const QRawFont &font) { QString key = fontKey(font); diff --git a/src/quick/scenegraph/qsgdefaultrendercontext_p.h b/src/quick/scenegraph/qsgdefaultrendercontext_p.h index eb62586a94..57aa4b4c90 100644 --- a/src/quick/scenegraph/qsgdefaultrendercontext_p.h +++ b/src/quick/scenegraph/qsgdefaultrendercontext_p.h @@ -95,6 +95,7 @@ public: bool hasBrokenIndexBufferObjects() const { return m_brokenIBOs; } int maxTextureSize() const override { return m_maxTextureSize; } + bool separateIndexBuffer() const; protected: static QString fontKey(const QRawFont &font); @@ -106,8 +107,6 @@ protected: bool m_serializedRender; bool m_attachToGLContext; QSGAtlasTexture::Manager *m_atlasManager; - - }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri index ac70c3153f..a9a71b1324 100644 --- a/src/quick/scenegraph/scenegraph.pri +++ b/src/quick/scenegraph/scenegraph.pri @@ -1,4 +1,3 @@ -# DEFINES += QSG_SEPARATE_INDEX_BUFFER # DEFINES += QSG_DISTANCEFIELD_CACHE_DEBUG emscripten: DEFINES += QSG_SEPARATE_INDEX_BUFFER diff --git a/src/src.pro b/src/src.pro index ff0e1e99bc..5177dfc743 100644 --- a/src/src.pro +++ b/src/src.pro @@ -8,9 +8,9 @@ SUBDIRS += \ qtHaveModule(gui):qtConfig(animation) { SUBDIRS += \ - quick \ - qmltest + quick + qtConfig(testlib): SUBDIRS += qmltest qtConfig(quick-particles): \ SUBDIRS += particles qtHaveModule(widgets): SUBDIRS += quickwidgets diff --git a/tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro b/tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro index 9cf323ba36..3f2c0ca390 100644 --- a/tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro +++ b/tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro @@ -1,6 +1,6 @@ CONFIG += testcase TARGET = tst_qdebugmessageservice -QT += qml network testlib gui-private core-private +QT += network testlib gui-private core-private osx:CONFIG -= app_bundle SOURCES += tst_qdebugmessageservice.cpp diff --git a/tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro b/tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro index b1e3835844..dc0120cd87 100644 --- a/tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro +++ b/tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro @@ -6,4 +6,4 @@ SOURCES += tst_qpacketprotocol.cpp include(../shared/debugutil.pri) -QT += qml network testlib gui-private core-private +QT += network testlib gui-private core-private diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/encodeQmlScope.qml b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/encodeQmlScope.qml new file mode 100644 index 0000000000..7ea048044f --- /dev/null +++ b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/data/encodeQmlScope.qml @@ -0,0 +1,19 @@ +import QtQuick 2.0 + +Item { + property int a: 0 + property int b: 0 + onAChanged: console.log("inline") + onBChanged: { + console.log("extra braces"); + } + + Timer { + interval: 10 + running: true + onTriggered: { + parent.a += 10; + parent.b -= 10; + } + } +} diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro index 90623c75a6..52d70bd1b1 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro +++ b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro @@ -20,4 +20,5 @@ OTHER_FILES += data/test.qml data/test.js \ data/changeBreakpoint.qml \ data/stepAction.qml \ data/breakpointRelocation.qml \ - data/createComponent.qml + data/createComponent.qml \ + data/encodeQmlScope.qml diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp index 3cd359cf48..660afce216 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp +++ b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp @@ -124,6 +124,7 @@ const char *QUIT_QMLFILE = "quit.qml"; const char *CHANGEBREAKPOINT_QMLFILE = "changeBreakpoint.qml"; const char *STEPACTION_QMLFILE = "stepAction.qml"; const char *BREAKPOINTRELOCATION_QMLFILE = "breakpointRelocation.qml"; +const char *ENCODEQMLSCOPE_QMLFILE = "encodeQmlScope.qml"; #define VARIANTMAPINIT \ QString obj("{}"); \ @@ -217,6 +218,8 @@ private slots: void getScripts_data() { targetData(); } void getScripts(); + void encodeQmlScope(); + private: ConnectResult init(bool qmlscene, const QString &qmlFile = QString(TEST_QMLFILE), bool blockMode = true, bool restrictServices = false); @@ -1455,6 +1458,70 @@ void tst_QQmlDebugJS::getScripts() QVERIFY(scripts.first().toMap()[QStringLiteral("name")].toString().endsWith(QStringLiteral("data/test.qml"))); } +void tst_QQmlDebugJS::encodeQmlScope() +{ + QString file(ENCODEQMLSCOPE_QMLFILE); + QCOMPARE(init(true, file), ConnectSuccess); + + int numFrames = 0; + int numExpectedScopes = 0; + int numReceivedScopes = 0; + bool isStopped = false; + bool scopesFailed = false; + + QObject::connect(m_client, &QJSDebugClient::failure, this, [&]() { + qWarning() << "received failure" << m_client->response; + scopesFailed = true; + m_process->stop(); + numFrames = 2; + isStopped = false; + }); + + QObject::connect(m_client, &QJSDebugClient::stopped, this, [&]() { + m_client->frame(); + isStopped = true; + }); + + QObject::connect(m_client, &QJSDebugClient::result, this, [&]() { + const QVariantMap value = m_client->parser.call( + QJSValueList() << QJSValue(QString(m_client->response))).toVariant().toMap(); + + const QMap<QString, QVariant> body = value.value("body").toMap(); + const QString command = value.value("command").toString(); + + if (command == QString("scope")) { + // If the scope commands fail we get a failure() signal above. + if (++numReceivedScopes == numExpectedScopes) { + m_client->continueDebugging(QJSDebugClient::Continue); + isStopped = false; + } + } else if (command == QString("frame")) { + + // We want at least a global scope and some kind of local scope here. + const QList<QVariant> scopes = body.value("scopes").toList(); + if (scopes.length() < 2) + scopesFailed = true; + + for (const QVariant &scope : scopes) { + ++numExpectedScopes; + m_client->scope(scope.toMap().value("index").toInt()); + } + + ++numFrames; + } + }); + + m_client->setBreakpoint(file, 6); + m_client->setBreakpoint(file, 8); + m_client->connect(); + + QTRY_COMPARE(numFrames, 2); + QVERIFY(numExpectedScopes > 3); + QVERIFY(!scopesFailed); + QTRY_VERIFY(!isStopped); + QCOMPARE(numReceivedScopes, numExpectedScopes); +} + QList<QQmlDebugClient *> tst_QQmlDebugJS::createClients() { m_client = new QJSDebugClient(m_connection); diff --git a/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp b/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp index 9f0501241d..5b3c0c5240 100644 --- a/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp +++ b/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp @@ -32,7 +32,6 @@ #include <private/qqmldebugconnector_p.h> #include <private/qqmldebugconnection_p.h> -#include <QtQml/qqmldebug.h> #include <QtQml/qqmlengine.h> #include <QtTest/qtest.h> diff --git a/tests/auto/qml/debugger/qqmlenginecontrol/qqmlenginecontrol.pro b/tests/auto/qml/debugger/qqmlenginecontrol/qqmlenginecontrol.pro index 73455bd903..36957628b2 100644 --- a/tests/auto/qml/debugger/qqmlenginecontrol/qqmlenginecontrol.pro +++ b/tests/auto/qml/debugger/qqmlenginecontrol/qqmlenginecontrol.pro @@ -8,7 +8,7 @@ include(../shared/debugutil.pri) TESTDATA = data/* -QT += core qml testlib gui-private core-private +QT += core testlib gui-private core-private OTHER_FILES += \ data/test.qml \ diff --git a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/qqmlenginedebuginspectorintegrationtest.pro b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/qqmlenginedebuginspectorintegrationtest.pro index 5f58e5ec7f..54244c6d16 100644 --- a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/qqmlenginedebuginspectorintegrationtest.pro +++ b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/qqmlenginedebuginspectorintegrationtest.pro @@ -1,7 +1,7 @@ CONFIG += testcase TARGET = tst_qqmlenginedebuginspectorintegration -QT += qml testlib gui-private core-private +QT += testlib gui-private core-private osx:CONFIG -= app_bundle SOURCES += tst_qqmlenginedebuginspectorintegration.cpp diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugservice.pro b/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugservice.pro index 33ee023c06..ed4224446e 100644 --- a/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugservice.pro +++ b/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugservice.pro @@ -10,4 +10,4 @@ include(../shared/debugutil.pri) DEFINES += QT_QML_DEBUG_NO_WARNING -QT += core-private qml-private quick-private testlib gui-private +QT += quick qml-private testlib diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp index 89217e7556..417b75e760 100644 --- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp +++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp @@ -53,6 +53,9 @@ #include <QtCore/qdebug.h> #include <QtCore/qthread.h> #include <QtCore/qabstractitemmodel.h> +#include <QtCore/qjsonobject.h> +#include <QtCore/qjsonarray.h> +#include <QtCore/qjsondocument.h> #define QVERIFYOBJECT(statement) \ do {\ @@ -82,6 +85,40 @@ public: QModelIndex modelIndex() { return QModelIndex(); } }; +class JsonTest : public QObject +{ + Q_OBJECT + Q_PROPERTY(QJsonObject data READ data WRITE setData NOTIFY dataChanged) + +public: + JsonTest(QObject *parent = 0) : QObject(parent) + { + m_data["foo"] = QJsonValue(12); + m_data["ttt"] = QJsonArray({4, 5, 4, 3, 2}); + m_data["a"] = QJsonValue(QJsonValue::Null); + m_data["b"] = QJsonValue(QJsonValue::Undefined); + m_data["c"] = QJsonValue("fffff"); + } + + QJsonObject data() const { return m_data; } + +signals: + void dataChanged(const QJsonObject &data); + +public slots: + void setData(const QJsonObject &data) + { + if (data != m_data) { + m_data = data; + emit dataChanged(data); + } + } + +private: + QJsonObject m_data; +}; + + class tst_QQmlEngineDebugService : public QObject { Q_OBJECT @@ -139,6 +176,7 @@ private slots: void regression_QTCREATORBUG_7451(); void queryObjectWithNonStreamableTypes(); + void jsonData(); void asynchronousCreate(); void invalidContexts(); void createObjectOnDestruction(); @@ -363,6 +401,11 @@ void tst_QQmlEngineDebugService::initTestCase() "CustomTypes {}" ; + qmlRegisterType<JsonTest>("JsonTest", 1, 0, "JsonTest"); + qml << "import JsonTest 1.0\n" + "JsonTest {}" + ; + for (int i=0; i<qml.count(); i++) { QQmlComponent component(m_engine); component.setData(qml[i], QUrl::fromLocalFile("")); @@ -676,7 +719,7 @@ void tst_QQmlEngineDebugService::queryRootContexts() // root context query sends only root object data - it doesn't fill in // the children or property info QCOMPARE(context.objects.count(), 0); - QCOMPARE(context.contexts.count(), 6); + QCOMPARE(context.contexts.count(), 7); QVERIFY(context.contexts[0].debugId >= 0); QCOMPARE(context.contexts[0].name, QString("tst_QQmlDebug_childContext")); } @@ -915,6 +958,24 @@ void tst_QQmlEngineDebugService::queryObjectWithNonStreamableTypes() QVariant(QLatin1String("QModelIndex()"))); } +void tst_QQmlEngineDebugService::jsonData() +{ + bool success; + + QmlDebugObjectReference rootObject = findRootObject(5, true); + QVERIFY(!rootObject.className.isEmpty()); + + m_dbg->queryObject(rootObject, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + + QmlDebugObjectReference obj = m_dbg->object(); + QVERIFY(!obj.className.isEmpty()); + + QCOMPARE(findProperty(obj.properties, "data").value, + QJsonDocument::fromJson("{\"a\":null,\"c\":\"fffff\",\"foo\":12,\"ttt\":[4,5,4,3,2]}") + .toVariant()); +} void tst_QQmlEngineDebugService::queryExpressionResult() { diff --git a/tests/auto/qml/debugger/qqmlinspector/qqmlinspector.pro b/tests/auto/qml/debugger/qqmlinspector/qqmlinspector.pro index fd07255ae5..3d4473c693 100644 --- a/tests/auto/qml/debugger/qqmlinspector/qqmlinspector.pro +++ b/tests/auto/qml/debugger/qqmlinspector/qqmlinspector.pro @@ -1,7 +1,7 @@ CONFIG += testcase TARGET = tst_qqmlinspector -QT += qml testlib gui-private core-private +QT += testlib gui-private core-private osx:CONFIG -= app_bundle SOURCES += tst_qqmlinspector.cpp diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro index 7c78b5fcb3..2a685ed877 100644 --- a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro +++ b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro @@ -8,7 +8,7 @@ include(../shared/debugutil.pri) TESTDATA = data/* -QT += core qml testlib testlib-private gui-private core-private +QT += testlib gui-private OTHER_FILES += \ data/pixmapCacheTest.qml \ diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp index 562804bc45..3cb315b355 100644 --- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp +++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp @@ -34,13 +34,12 @@ #include <private/qqmldebugconnection_p.h> #include <QtTest/qtest.h> -#include <private/qtestresult_p.h> #include <QtCore/qlibraryinfo.h> #include <QtGui/private/qguiapplication_p.h> #include <QtGui/qpa/qplatformintegration.h> -class QQmlProfilerTestClient : public QQmlProfilerEventReceiver, public QQmlProfilerDefinitions +class QQmlProfilerTestClient : public QQmlProfilerEventReceiver { Q_OBJECT @@ -229,8 +228,8 @@ private: bool m_isComplete = false; // Don't use ({...}) here as MSVC will interpret that as the "QVector(int size)" ctor. - const QVector<qint64> m_rangeStart = (QVector<qint64>() << QQmlProfilerDefinitions::RangeStart); - const QVector<qint64> m_rangeEnd = (QVector<qint64>() << QQmlProfilerDefinitions::RangeEnd); + const QVector<qint64> m_rangeStart = (QVector<qint64>() << RangeStart); + const QVector<qint64> m_rangeEnd = (QVector<qint64>() << RangeEnd); }; #define VERIFY(type, position, expected, checks, numbers) \ @@ -247,7 +246,7 @@ QQmlDebugTest::ConnectResult tst_QQmlProfilerService::connect( // ### Still using qmlscene due to QTBUG-33377 return QQmlDebugTest::connect( QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene", - restrictServices ? QQmlDebuggingEnabler::profilerServices().join(',') : QString(), + restrictServices ? "CanvasFrameRate,EngineControl,DebugMessages" : QString(), testFile(file), block); } @@ -272,15 +271,11 @@ void tst_QQmlProfilerService::checkTraceReceived() QVector<qint64> numbers; // must start with "StartTrace" - QQmlProfilerEventType expected(QQmlProfilerDefinitions::Event, - QQmlProfilerDefinitions::MaximumRangeType, - QQmlProfilerDefinitions::StartTrace); + QQmlProfilerEventType expected(Event, MaximumRangeType, StartTrace); VERIFY(MessageListAsynchronous, 0, expected, CheckMessageType | CheckDetailType, numbers); // must end with "EndTrace" - expected = QQmlProfilerEventType(QQmlProfilerDefinitions::Event, - QQmlProfilerDefinitions::MaximumRangeType, - QQmlProfilerDefinitions::EndTrace); + expected = QQmlProfilerEventType(Event, MaximumRangeType, EndTrace); VERIFY(MessageListAsynchronous, m_client->asynchronousMessages.length() - 1, expected, CheckMessageType | CheckDetailType, numbers); } @@ -299,15 +294,15 @@ void tst_QQmlProfilerService::checkJsHeap() const qint64 amount = message.number<qint64>(0); const QQmlProfilerEventType &type = m_client->types.at(message.typeIndex()); switch (type.detailType()) { - case QV4::Profiling::HeapPage: + case HeapPage: allocated += amount; seen_alloc = true; break; - case QV4::Profiling::SmallItem: + case SmallItem: used += amount; seen_small = true; break; - case QV4::Profiling::LargeItem: + case LargeItem: allocated += amount; used += amount; seen_large = true; @@ -548,28 +543,27 @@ void tst_QQmlProfilerService::pixmapCacheData() checkTraceReceived(); checkJsHeap(); - auto createType = [](QQmlProfilerDefinitions::PixmapEventType type) { - return QQmlProfilerEventType(QQmlProfilerDefinitions::PixmapCacheEvent, - QQmlProfilerDefinitions::MaximumRangeType, type); + auto createType = [](PixmapEventType type) { + return QQmlProfilerEventType(PixmapCacheEvent, MaximumRangeType, type); }; QVector<qint64> numbers; // image starting to load - VERIFY(MessageListPixmap, 0, createType(QQmlProfilerDefinitions::PixmapLoadingStarted), + VERIFY(MessageListPixmap, 0, createType(PixmapLoadingStarted), CheckMessageType | CheckDetailType, numbers); // image size numbers = QVector<qint64>({2, 2, 1}); - VERIFY(MessageListPixmap, 1, createType(QQmlProfilerDefinitions::PixmapSizeKnown), + VERIFY(MessageListPixmap, 1, createType(PixmapSizeKnown), CheckMessageType | CheckDetailType | CheckNumbers, numbers); // image loaded - VERIFY(MessageListPixmap, 2, createType(QQmlProfilerDefinitions::PixmapLoadingFinished), + VERIFY(MessageListPixmap, 2, createType(PixmapLoadingFinished), CheckMessageType | CheckDetailType, numbers); // cache size - VERIFY(MessageListPixmap, 3, createType(QQmlProfilerDefinitions::PixmapCacheCountChanged), + VERIFY(MessageListPixmap, 3, createType(PixmapCacheCountChanged), CheckMessageType | CheckDetailType, numbers); } @@ -597,8 +591,8 @@ void tst_QQmlProfilerService::scenegraphData() if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) { foreach (const QQmlProfilerEvent &msg, m_client->asynchronousMessages) { const QQmlProfilerEventType &type = m_client->types.at(msg.typeIndex()); - if (type.message() == QQmlProfilerDefinitions::SceneGraphFrame) { - if (type.detailType() == QQmlProfilerDefinitions::SceneGraphContextFrame) { + if (type.message() == SceneGraphFrame) { + if (type.detailType() == SceneGraphContextFrame) { contextFrameTime = msg.timestamp(); break; } @@ -610,7 +604,7 @@ void tst_QQmlProfilerService::scenegraphData() #endif foreach (const QQmlProfilerEvent &msg, m_client->asynchronousMessages) { const QQmlProfilerEventType &type = m_client->types.at(msg.typeIndex()); - if (type.detailType() == QQmlProfilerDefinitions::SceneGraphRendererFrame) { + if (type.detailType() == SceneGraphRendererFrame) { QVERIFY(msg.timestamp() >= contextFrameTime); renderFrameTime = msg.timestamp(); break; @@ -621,7 +615,7 @@ void tst_QQmlProfilerService::scenegraphData() foreach (const QQmlProfilerEvent &msg, m_client->asynchronousMessages) { const QQmlProfilerEventType &type = m_client->types.at(msg.typeIndex()); - if (type.detailType() == QQmlProfilerDefinitions::SceneGraphRenderLoopFrame) { + if (type.detailType() == SceneGraphRenderLoopFrame) { if (msg.timestamp() >= contextFrameTime) { // Make sure SceneGraphRenderLoopFrame is not between SceneGraphContextFrame and // SceneGraphRendererFrame. A SceneGraphRenderLoopFrame before everything else is @@ -664,8 +658,7 @@ void tst_QQmlProfilerService::signalSourceLocation() auto createType = [](int line, int column) { return QQmlProfilerEventType( - QQmlProfilerDefinitions::MaximumMessage, - QQmlProfilerDefinitions::HandlingSignal, -1, + MaximumMessage, HandlingSignal, -1, QQmlProfilerEventLocation(QLatin1String("signalSourceLocation.qml"), line, column)); }; @@ -684,23 +677,21 @@ void tst_QQmlProfilerService::javascript() checkTraceReceived(); checkJsHeap(); - VERIFY(MessageListJavaScript, 2, QQmlProfilerEventType(QQmlProfilerDefinitions::MaximumMessage, - QQmlProfilerDefinitions::Javascript), + VERIFY(MessageListJavaScript, 2, QQmlProfilerEventType(MaximumMessage, Javascript), CheckMessageType | CheckDetailType | CheckNumbers, m_rangeStart); VERIFY(MessageListJavaScript, 3, - QQmlProfilerEventType(QQmlProfilerDefinitions::MaximumMessage, - QQmlProfilerDefinitions::Javascript, -1, - QQmlProfilerEventLocation(QLatin1String("javascript.qml"), 4, 5)), + QQmlProfilerEventType( + MaximumMessage, Javascript, -1, + QQmlProfilerEventLocation(QLatin1String("javascript.qml"), 4, 5)), CheckType | CheckNumbers, m_rangeStart); VERIFY(MessageListJavaScript, 4, QQmlProfilerEventType( - QQmlProfilerDefinitions::MaximumMessage, QQmlProfilerDefinitions::Javascript, -1, + MaximumMessage, Javascript, -1, QQmlProfilerEventLocation(), QLatin1String("something")), CheckMessageType | CheckDetailType | CheckDataEndsWith | CheckNumbers, m_rangeStart); - VERIFY(MessageListJavaScript, 10, QQmlProfilerEventType(QQmlProfilerDefinitions::MaximumMessage, - QQmlProfilerDefinitions::Javascript), + VERIFY(MessageListJavaScript, 10, QQmlProfilerEventType(MaximumMessage, Javascript), CheckMessageType | CheckDetailType | CheckNumbers, m_rangeEnd); } @@ -726,8 +717,7 @@ void tst_QQmlProfilerService::translationBinding() checkTraceReceived(); checkJsHeap(); - const QQmlProfilerEventType type(QQmlProfilerDefinitions::MaximumMessage, - QQmlProfilerDefinitions::Binding); + const QQmlProfilerEventType type(MaximumMessage, Binding); VERIFY(MessageListQML, 4, type, CheckDetailType | CheckMessageType | CheckNumbers, m_rangeStart); @@ -746,7 +736,7 @@ void tst_QQmlProfilerService::memory() int smallItems = 0; for (auto message : m_client->jsHeapMessages) { const QQmlProfilerEventType &type = m_client->types[message.typeIndex()]; - if (type.detailType() == QV4::Profiling::SmallItem) + if (type.detailType() == SmallItem) ++smallItems; } @@ -756,8 +746,7 @@ void tst_QQmlProfilerService::memory() static bool hasCompileEvents(const QVector<QQmlProfilerEventType> &types) { for (const QQmlProfilerEventType &type : types) { - if (type.message() == QQmlProfilerDefinitions::MaximumMessage - && type.rangeType() == QQmlProfilerDefinitions::Compiling) + if (type.message() == MaximumMessage && type.rangeType() == Compiling) return true; } return false; @@ -776,29 +765,29 @@ void tst_QQmlProfilerService::compile() checkTraceReceived(); checkJsHeap(); - QQmlProfilerDefinitions::Message rangeStage = QQmlProfilerDefinitions::MaximumMessage; + Message rangeStage = MaximumMessage; for (auto message : m_client->qmlMessages) { const QQmlProfilerEventType &type = m_client->types[message.typeIndex()]; - if (type.rangeType() == QQmlProfilerDefinitions::Compiling) { + if (type.rangeType() == Compiling) { switch (rangeStage) { - case QQmlProfilerDefinitions::MaximumMessage: - QCOMPARE(message.rangeStage(), QQmlProfilerDefinitions::RangeStart); + case MaximumMessage: + QCOMPARE(message.rangeStage(), RangeStart); break; - case QQmlProfilerDefinitions::RangeStart: - QCOMPARE(message.rangeStage(), QQmlProfilerDefinitions::RangeEnd); + case RangeStart: + QCOMPARE(message.rangeStage(), RangeEnd); break; default: QFAIL("Wrong range stage"); } rangeStage = message.rangeStage(); - QCOMPARE(type.message(), QQmlProfilerDefinitions::MaximumMessage); + QCOMPARE(type.message(), MaximumMessage); QCOMPARE(type.location().filename(), testFileUrl("test.qml").toString()); QCOMPARE(type.location().line(), 0); QCOMPARE(type.location().column(), 0); } } - QCOMPARE(rangeStage, QQmlProfilerDefinitions::RangeEnd); + QCOMPARE(rangeStage, RangeEnd); } QTEST_MAIN(tst_QQmlProfilerService) diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp index 4ce0f9fd89..c65c592f10 100644 --- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp +++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp @@ -297,6 +297,7 @@ private slots: // context access: void readArguments_data() { redundancy_data(); } void readArguments(); + void readComplicatedArguments(); void readLocals_data() { redundancy_data(); } void readLocals(); void readObject_data() { redundancy_data(); } @@ -549,6 +550,27 @@ void tst_qv4debugger::readArguments() QCOMPARE(frame0.value(QStringLiteral("b")).toString(), QStringLiteral("two")); } +void tst_qv4debugger::readComplicatedArguments() +{ + m_debuggerAgent->collector.setRedundantRefs(false); + m_debuggerAgent->m_captureContextInfo = true; + QString script = + "var f = function(a) {\n" + " a = 12;\n" + " return a;\n" + "}\n" + "f(1, 2);\n"; + debugger()->addBreakPoint("readArguments", 3); + evaluateJavaScript(script, "readArguments"); + QVERIFY(m_debuggerAgent->m_wasPaused); + QVERIFY(m_debuggerAgent->m_capturedScope.size() > 1); + const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedScope.at(0); + QCOMPARE(frame0.size(), 1); + QVERIFY(frame0.contains(QStringLiteral("a"))); + QCOMPARE(frame0.type(QStringLiteral("a")), QStringLiteral("number")); + QCOMPARE(frame0.value(QStringLiteral("a")).toInt(), 12); +} + void tst_qv4debugger::readLocals() { QFETCH(bool, redundantRefs); diff --git a/tests/auto/qml/debugger/shared/debugutil.cpp b/tests/auto/qml/debugger/shared/debugutil.cpp index 8ecbe53822..b118b22c64 100644 --- a/tests/auto/qml/debugger/shared/debugutil.cpp +++ b/tests/auto/qml/debugger/shared/debugutil.cpp @@ -31,8 +31,6 @@ #include <private/qqmldebugconnection_p.h> -#include <QtQml/qqmldebug.h> - #include <QtCore/qeventloop.h> #include <QtCore/qtimer.h> @@ -52,15 +50,23 @@ bool QQmlDebugTest::waitForSignal(QObject *receiver, const char *member, int tim QList<QQmlDebugClient *> QQmlDebugTest::createOtherClients(QQmlDebugConnection *connection) { QList<QQmlDebugClient *> ret; - foreach (const QString &service, QQmlDebuggingEnabler::debuggerServices()) { + + static const auto debuggerServices + = QStringList({"V8Debugger", "QmlDebugger", "DebugMessages"}); + static const auto inspectorServices + = QStringList({"QmlInspector"}); + static const auto profilerServices + = QStringList({"CanvasFrameRate", "EngineControl", "DebugMessages"}); + + for (const QString &service : debuggerServices) { if (!connection->client(service)) ret << new QQmlDebugClient(service, connection); } - foreach (const QString &service, QQmlDebuggingEnabler::inspectorServices()) { + for (const QString &service : inspectorServices) { if (!connection->client(service)) ret << new QQmlDebugClient(service, connection); } - foreach (const QString &service, QQmlDebuggingEnabler::profilerServices()) { + for (const QString &service : profilerServices) { if (!connection->client(service)) ret << new QQmlDebugClient(service, connection); } diff --git a/tests/auto/qml/ecmascripttests/test262 b/tests/auto/qml/ecmascripttests/test262 -Subproject 40b4f28e98c416a092e26aa17489bf94ccb8bf4 +Subproject e505c11eebe5a389a7d47a4bf570c66469740b0 diff --git a/tests/auto/qml/ecmascripttests/test262.py b/tests/auto/qml/ecmascripttests/test262.py index ae4c54df9d..e055c7a8e7 100755 --- a/tests/auto/qml/ecmascripttests/test262.py +++ b/tests/auto/qml/ecmascripttests/test262.py @@ -555,7 +555,7 @@ def Main(): # Uncomment the next line for more logging info. #logging.basicConfig(level=logging.DEBUG) # Some date tests rely on being run in pacific time and the USA's locale: - os.environ["TZ"] = "America/Vancouver" + os.environ["TZ"] = "America/Los_Angeles" # it *matters* that this is (7m8s) *East* of PST's nominal meridian ! os.environ["LANG"] = "en_US.UTF-8" os.environ["LC_TIME"] = "en_US.UTF-8" parser = BuildOptions() diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index f862cdb048..bb923951a8 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -201,10 +201,13 @@ private slots: void basicBlockMergeAfterLoopPeeling(); + void modulusCrash(); void malformedExpression(); void scriptScopes(); + void protoChanges_QTBUG68369(); + signals: void testSignal(); }; @@ -4135,6 +4138,15 @@ void tst_QJSEngine::basicBlockMergeAfterLoopPeeling() } +void tst_QJSEngine::modulusCrash() +{ + QJSEngine engine; + QJSValue result = engine.evaluate( + "var a = -2147483648; var b = -1; var c = a % b; c;" + ); + QVERIFY(result.isNumber() && result.toNumber() == 0.); +} + void tst_QJSEngine::malformedExpression() { QJSEngine engine; @@ -4157,6 +4169,22 @@ void tst_QJSEngine::scriptScopes() QCOMPARE(use.toInt(), 42); } +void tst_QJSEngine::protoChanges_QTBUG68369() +{ + QJSEngine engine; + QJSValue ok = engine.evaluate( + "var o = { x: true };" + "var p1 = {};" + "var p2 = {};" + "o.__proto__ = p1;" + "o.__proto__ = p2;" + "o.__proto__ = p1;" + "p1.y = true;" + "o.y" + ); + QVERIFY(ok.toBool() == true); +} + QTEST_MAIN(tst_QJSEngine) #include "tst_qjsengine.moc" diff --git a/tests/auto/qml/qmlcachegen/Enums.qml b/tests/auto/qml/qmlcachegen/Enums.qml new file mode 100644 index 0000000000..830babb73e --- /dev/null +++ b/tests/auto/qml/qmlcachegen/Enums.qml @@ -0,0 +1,9 @@ +import QtQml 2.0 +QtObject { + enum Test { + First = 100, + Second = 200 + } + property int value: 0 + Component.onCompleted: value = Enums.Second +} diff --git a/tests/auto/qml/qmlcachegen/jsimport.qml b/tests/auto/qml/qmlcachegen/jsimport.qml new file mode 100644 index 0000000000..9c40878e60 --- /dev/null +++ b/tests/auto/qml/qmlcachegen/jsimport.qml @@ -0,0 +1,6 @@ +import QtQml 2.0 +import "script.js" as Script + +QtObject { + property int value: Script.getter() +} diff --git a/tests/auto/qml/qmlcachegen/library.js b/tests/auto/qml/qmlcachegen/library.js new file mode 100644 index 0000000000..51fb41dc23 --- /dev/null +++ b/tests/auto/qml/qmlcachegen/library.js @@ -0,0 +1,4 @@ + +function getter() { + return 42; +} diff --git a/tests/auto/qml/qmlcachegen/qmlcachegen.pro b/tests/auto/qml/qmlcachegen/qmlcachegen.pro index a2f963e8c3..40de4548a7 100644 --- a/tests/auto/qml/qmlcachegen/qmlcachegen.pro +++ b/tests/auto/qml/qmlcachegen/qmlcachegen.pro @@ -12,4 +12,8 @@ RESOURCES += versionchecks.qml RESOURCES += trickypaths.qrc +RESOURCES += jsimport.qml script.js library.js + +RESOURCES += Enums.qml + QT += core-private qml-private testlib diff --git a/tests/auto/qml/qmlcachegen/script.js b/tests/auto/qml/qmlcachegen/script.js new file mode 100644 index 0000000000..fa55f9069e --- /dev/null +++ b/tests/auto/qml/qmlcachegen/script.js @@ -0,0 +1,6 @@ + +.import "library.js" as Library + +function getter() { + return Library.getter() +} diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp index 5c1692f086..3b7d268f7b 100644 --- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp +++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp @@ -54,6 +54,10 @@ private slots: void workerScripts(); void trickyPaths(); + + void scriptImport(); + + void enums(); }; // A wrapper around QQmlComponent to ensure the temporary reference counts @@ -416,6 +420,24 @@ void tst_qmlcachegen::trickyPaths() QCOMPARE(obj->property("success").toInt(), 42); } +void tst_qmlcachegen::scriptImport() +{ + QQmlEngine engine; + CleanlyLoadingComponent component(&engine, QUrl("qrc:///jsimport.qml")); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); + QTRY_COMPARE(obj->property("value").toInt(), 42); +} + +void tst_qmlcachegen::enums() +{ + QQmlEngine engine; + CleanlyLoadingComponent component(&engine, QUrl("qrc:///Enums.qml")); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); + QTRY_COMPARE(obj->property("value").toInt(), 200); +} + QTEST_GUILESS_MAIN(tst_qmlcachegen) #include "tst_qmlcachegen.moc" diff --git a/tests/auto/qml/qqmlcomponent/data/InitialPropertyTest.qml b/tests/auto/qml/qqmlcomponent/data/InitialPropertyTest.qml new file mode 100644 index 0000000000..7de276f2d8 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/InitialPropertyTest.qml @@ -0,0 +1,4 @@ +import QtQml 2.0 +QtObject { + property bool ok: false +} diff --git a/tests/auto/qml/qqmlcomponent/data/nonExistentInitialProperty.qml b/tests/auto/qml/qqmlcomponent/data/nonExistentInitialProperty.qml new file mode 100644 index 0000000000..ef89e46088 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/nonExistentInitialProperty.qml @@ -0,0 +1,9 @@ +import QtQml 2.0 +QtObject { + property Component factory: Qt.createComponent(Qt.resolvedUrl("InitialPropertyTest.qml"), Component.PreferSynchronous) + property var incubator + function startIncubation() + { + incubator = factory.incubateObject(null, { ok: true, nonExistent: 42 }, Qt.Asynchronous) + } +} diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp index 6a0dc28ca4..3a70890362 100644 --- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp +++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp @@ -117,6 +117,7 @@ private slots: void recursion(); void recursionContinuation(); void callingContextForInitialProperties(); + void setNonExistentInitialProperty(); void relativeUrl_data(); void relativeUrl(); @@ -583,6 +584,23 @@ void tst_qqmlcomponent::callingContextForInitialProperties() QVERIFY(checker->scopeObject->metaObject()->indexOfProperty("incubatedObject") != -1); } +void tst_qqmlcomponent::setNonExistentInitialProperty() +{ + QQmlIncubationController controller; + QQmlEngine engine; + engine.setIncubationController(&controller); + QQmlComponent component(&engine, testFileUrl("nonExistentInitialProperty.qml")); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); + QMetaObject::invokeMethod(obj.data(), "startIncubation"); + QJSValue incubatorStatus = obj->property("incubator").value<QJSValue>(); + incubatorStatus.property("forceCompletion").callWithInstance(incubatorStatus); + QJSValue objectWrapper = incubatorStatus.property("object"); + QVERIFY(objectWrapper.isQObject()); + QPointer<QObject> object(objectWrapper.toQObject()); + QVERIFY(object->property("ok").toBool()); +} + void tst_qqmlcomponent::relativeUrl_data() { QTest::addColumn<QUrl>("url"); diff --git a/tests/auto/qml/qqmlengine/data/qrcurls.js b/tests/auto/qml/qqmlengine/data/qrcurls.js new file mode 100644 index 0000000000..15a4d5a70c --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/qrcurls.js @@ -0,0 +1 @@ +function someFunction() {} diff --git a/tests/auto/qml/qqmlengine/data/qrcurls.qml b/tests/auto/qml/qqmlengine/data/qrcurls.qml new file mode 100644 index 0000000000..e879577e10 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/qrcurls.qml @@ -0,0 +1,4 @@ +import QtQml 2.0 + +QtObject { +} diff --git a/tests/auto/qml/qqmlengine/qqmlengine.pro b/tests/auto/qml/qqmlengine/qqmlengine.pro index 8d1e149d62..d2eb92bfd5 100644 --- a/tests/auto/qml/qqmlengine/qqmlengine.pro +++ b/tests/auto/qml/qqmlengine/qqmlengine.pro @@ -12,3 +12,7 @@ boot2qt: { # GC corruption test is too heavy for qemu-arm DEFINES += SKIP_GCCORRUPTION_TEST } + +RESOURCES += \ + data/qrcurls.qml \ + data/qrcurls.js diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index 52e18011cb..95098648fa 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -77,6 +77,8 @@ private slots: void testGCCorruption(); void testGroupedPropertyRevisions(); void componentFromEval(); + void qrcUrls(); + void cppSignalAndEval(); public slots: QObject *createAQObjectForOwnershipTest () @@ -897,6 +899,63 @@ void tst_qqmlengine::componentFromEval() QVERIFY(!item.isNull()); } +void tst_qqmlengine::qrcUrls() +{ + QQmlEngine engine; + QQmlEnginePrivate *pEngine = QQmlEnginePrivate::get(&engine); + + { + QQmlRefPointer<QQmlTypeData> oneQml(pEngine->typeLoader.getType(QUrl("qrc:/qrcurls.qml")), + QQmlRefPointer<QQmlTypeData>::Adopt); + QVERIFY(oneQml != nullptr); + QQmlRefPointer<QQmlTypeData> twoQml(pEngine->typeLoader.getType(QUrl("qrc:///qrcurls.qml")), + QQmlRefPointer<QQmlTypeData>::Adopt); + QVERIFY(twoQml != nullptr); + QCOMPARE(oneQml, twoQml); + } + + { + QQmlRefPointer<QQmlTypeData> oneJS(pEngine->typeLoader.getType(QUrl("qrc:/qrcurls.js")), + QQmlRefPointer<QQmlTypeData>::Adopt); + QVERIFY(oneJS != nullptr); + QQmlRefPointer<QQmlTypeData> twoJS(pEngine->typeLoader.getType(QUrl("qrc:///qrcurls.js")), + QQmlRefPointer<QQmlTypeData>::Adopt); + QVERIFY(twoJS != nullptr); + QCOMPARE(oneJS, twoJS); + } +} + +class ObjectCaller : public QObject +{ + Q_OBJECT +signals: + void doubleReply(const double a); +}; + +void tst_qqmlengine::cppSignalAndEval() +{ + ObjectCaller objectCaller; + QQmlEngine engine; + engine.rootContext()->setContextProperty(QLatin1Literal("CallerCpp"), &objectCaller); + QQmlComponent c(&engine); + c.setData("import QtQuick 2.9\n" + "Item {\n" + " property var r: 0\n" + " Connections {\n" + " target: CallerCpp;\n" + " onDoubleReply: {\n" + " eval('var z = 1');\n" + " r = a;\n" + " }\n" + " }\n" + "}", + QUrl(QStringLiteral("qrc:/main.qml"))); + QScopedPointer<QObject> object(c.create()); + QVERIFY(!object.isNull()); + emit objectCaller.doubleReply(1.1234); + QCOMPARE(object->property("r"), 1.1234); +} + QTEST_MAIN(tst_qqmlengine) #include "tst_qqmlengine.moc" diff --git a/tests/auto/qml/qqmlinfo/data/Component.qml b/tests/auto/qml/qqmlinfo/data/Component.qml new file mode 100644 index 0000000000..fefbbfae76 --- /dev/null +++ b/tests/auto/qml/qqmlinfo/data/Component.qml @@ -0,0 +1,8 @@ +import QtQml 2.0 + +QtObject { + property Component delegate: Component { + QtObject { + } + } +} diff --git a/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp b/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp index ada3f9e37b..5ff72de0a0 100644 --- a/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp +++ b/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp @@ -50,6 +50,7 @@ private slots: void types(); void chaining(); void messageTypes(); + void component(); private: QQmlEngine engine; @@ -216,6 +217,19 @@ void tst_qqmlinfo::messageTypes() qmlWarning(nullptr) << QLatin1String("warning"); } +void tst_qqmlinfo::component() +{ + QQmlComponent component(&engine, testFileUrl("Component.qml")); + QScopedPointer<QObject> object(component.create()); + QVERIFY(object != nullptr); + QQmlComponent *delegate = qobject_cast<QQmlComponent*>(object->property("delegate").value<QObject*>()); + QVERIFY(delegate); + + QString message = component.url().toString() + ":4:34: QML Component: Delegate error"; + QTest::ignoreMessage(QtInfoMsg, qPrintable(message)); + qmlInfo(delegate) << "Delegate error"; +} + QTEST_MAIN(tst_qqmlinfo) #include "tst_qqmlinfo.moc" diff --git a/tests/auto/qml/qqmlinstantiator/stringmodel.h b/tests/auto/qml/qqmlinstantiator/stringmodel.h index b01817375a..6ae3cbb6ee 100644 --- a/tests/auto/qml/qqmlinstantiator/stringmodel.h +++ b/tests/auto/qml/qqmlinstantiator/stringmodel.h @@ -60,7 +60,7 @@ public: endInsertRows(); } - int rowCount(const QModelIndex &) const + int rowCount(const QModelIndex &) const override { return items.count(); } @@ -70,7 +70,7 @@ public: return roles; } - virtual int columnCount(const QModelIndex &) const + int columnCount(const QModelIndex &) const override { return 1; } @@ -80,7 +80,7 @@ public: return rowCount(QModelIndex()) > 0; } - virtual QModelIndex index(int row, int column, const QModelIndex &parent) const + QModelIndex index(int row, int column, const QModelIndex &parent) const override { Q_UNUSED(column); if (row>=0 && row<rowCount(parent)) @@ -89,12 +89,12 @@ public: return QModelIndex(); } - virtual QModelIndex parent(const QModelIndex &) const + QModelIndex parent(const QModelIndex &) const override { return QModelIndex(); } - QVariant data (const QModelIndex & index, int role) const + QVariant data (const QModelIndex & index, int role) const override { int row = index.row(); if ((row<0) || (row>=items.count())) diff --git a/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp b/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp index 6b8002cce5..21b0508e4d 100644 --- a/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp +++ b/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp @@ -204,6 +204,7 @@ void tst_qqmllistmodelworkerscript::dynamic_data() QTest::newRow("get4") << "{append({'foo':123});get(0).foo}" << 123 << "" << dr; QTest::newRow("get-modify1") << "{append({'foo':123,'bar':456});get(0).foo = 333;get(0).foo}" << 333 << "" << dr; QTest::newRow("get-modify2") << "{append({'z':1});append({'foo':123,'bar':456});get(1).bar = 999;get(1).bar}" << 999 << "" << dr; + QTest::newRow("get-set") << "{append({'foo':123});get(0).foo;setProperty(0, 'foo', 999);get(0).foo}" << 999 << "" << dr; QTest::newRow("append1") << "{append({'foo':123});count}" << 1 << "" << dr; QTest::newRow("append2") << "{append({'foo':123,'bar':456});count}" << 1 << "" << dr; diff --git a/tests/auto/qml/qqmlmetatype/qqmlmetatype.pro b/tests/auto/qml/qqmlmetatype/qqmlmetatype.pro index 0d8de91931..345bc59615 100644 --- a/tests/auto/qml/qqmlmetatype/qqmlmetatype.pro +++ b/tests/auto/qml/qqmlmetatype/qqmlmetatype.pro @@ -6,4 +6,8 @@ macx:CONFIG -= app_bundle TESTDATA = data/* include (../../shared/util.pri) +qmlfiles.files = data/CompositeType.qml +qmlfiles.prefix = /tstqqmlmetatype +RESOURCES += qmlfiles + QT += core-private gui-private qml-private testlib diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp index ff3361ff82..1d0d353668 100644 --- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp +++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp @@ -62,6 +62,8 @@ private slots: void defaultObject(); void unregisterCustomType(); void unregisterCustomSingletonType(); + + void normalizeUrls(); }; class TestType : public QObject @@ -523,6 +525,18 @@ void tst_qqmlmetatype::unregisterCustomSingletonType() } } +void tst_qqmlmetatype::normalizeUrls() +{ + const QUrl url("qrc:///tstqqmlmetatype/data/CompositeType.qml"); + QVERIFY(!QQmlMetaType::qmlType(url).isValid()); + const auto registrationId = qmlRegisterType(url, "Test", 1, 0, "ResourceCompositeType"); + QVERIFY(QQmlMetaType::qmlType(url, /*includeNonFileImports=*/true).isValid()); + QUrl normalizedURL("qrc:/tstqqmlmetatype/data/CompositeType.qml"); + QVERIFY(QQmlMetaType::qmlType(normalizedURL, /*includeNonFileImports=*/true).isValid()); + qmlUnregisterType(registrationId); + QVERIFY(!QQmlMetaType::qmlType(url, /*includeNonFileImports=*/true).isValid()); +} + QTEST_MAIN(tst_qqmlmetatype) #include "tst_qqmlmetatype.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp index fac3ff15fd..97ca3fa1de 100644 --- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp @@ -29,6 +29,7 @@ #include <qdir.h> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> +#include <QtQml/qqmlcontext.h> #include <QtQml/qqmlextensionplugin.h> #include <QtCore/qjsondocument.h> #include <QtCore/qjsonarray.h> @@ -332,6 +333,29 @@ void tst_qqmlmoduleplugin::remoteImportWithUnquotedUri() VERIFY_ERRORS(0); } +static QByteArray msgComponentError(const QQmlComponent &c, const QQmlEngine *engine /* = 0 */) +{ + QString result; + const QList<QQmlError> errors = c.errors(); + QTextStream str(&result); + str << "Component '" << c.url().toString() << "' has " << errors.size() << " errors: '"; + for (int i = 0; i < errors.size(); ++i) { + if (i) + str << ", '"; + str << errors.at(i).toString() << '\''; + } + if (!engine) { + if (QQmlContext *context = c.creationContext()) + engine = context->engine(); + } + if (engine) { + str << " Import paths: (" << engine->importPathList().join(QStringLiteral(", ")) + << ") Plugin paths: (" << engine->pluginPathList().join(QStringLiteral(", ")) + << ')'; + } + return result.toLocal8Bit(); +} + // QTBUG-17324 void tst_qqmlmoduleplugin::importsMixedQmlCppPlugin() @@ -345,7 +369,7 @@ void tst_qqmlmoduleplugin::importsMixedQmlCppPlugin() QQmlComponent component(&engine, testFileUrl(QStringLiteral("importsMixedQmlCppPlugin.qml"))); QObject *o = component.create(); - QVERIFY2(o != nullptr, QQmlDataTest::msgComponentError(component, &engine)); + QVERIFY2(o != nullptr, msgComponentError(component, &engine)); QCOMPARE(o->property("test").toBool(), true); delete o; } @@ -354,7 +378,7 @@ void tst_qqmlmoduleplugin::importsMixedQmlCppPlugin() QQmlComponent component(&engine, testFileUrl(QStringLiteral("importsMixedQmlCppPlugin.2.qml"))); QObject *o = component.create(); - QVERIFY2(o != nullptr, QQmlDataTest::msgComponentError(component, &engine)); + QVERIFY2(o != nullptr, msgComponentError(component, &engine)); QCOMPARE(o->property("test").toBool(), true); QCOMPARE(o->property("test2").toBool(), true); delete o; diff --git a/tests/auto/qml/qqmltypeloader/data/Base.qml b/tests/auto/qml/qqmltypeloader/data/Base.qml new file mode 100644 index 0000000000..431c659424 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/Base.qml @@ -0,0 +1,3 @@ +import QtQml 2.0 + +QtObject {} diff --git a/tests/auto/qml/qqmltypeloader/data/Load.qml b/tests/auto/qml/qqmltypeloader/data/Load.qml new file mode 100644 index 0000000000..0b893bb5cd --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/Load.qml @@ -0,0 +1,11 @@ +import QtQuick 2.0 + +Item { + property int xy: loader.xy + Loader { + id: loader + asynchronous: true + source: 'Base.qml' + property int xy: item.xy + } +} diff --git a/tests/auto/qml/qqmltypeloader/data/redirected/Imported.qml b/tests/auto/qml/qqmltypeloader/data/redirected/Imported.qml new file mode 100644 index 0000000000..62954fe1b2 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/redirected/Imported.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +QtObject { + property int xy: 323232 +} diff --git a/tests/auto/qml/qqmltypeloader/data/redirected/Redirected.qml b/tests/auto/qml/qqmltypeloader/data/redirected/Redirected.qml new file mode 100644 index 0000000000..40fec5ed31 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/redirected/Redirected.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +Imported { + +} diff --git a/tests/auto/qml/qqmltypeloader/data/redirected/qmldir b/tests/auto/qml/qqmltypeloader/data/redirected/qmldir new file mode 100644 index 0000000000..8eb1fa5c18 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/redirected/qmldir @@ -0,0 +1 @@ +Imported 1.0 Imported.qml diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp index c10a8a08c1..d336d033a3 100644 --- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp +++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp @@ -33,6 +33,7 @@ #include <QtQuick/qquickitem.h> #include <QtQml/private/qqmlengine_p.h> #include <QtQml/private/qqmltypeloader_p.h> +#include "../../shared/testhttpserver.h" #include "../../shared/util.h" class tst_QQMLTypeLoader : public QQmlDataTest @@ -48,6 +49,7 @@ private slots: void keepSingleton(); void keepRegistrations(); void intercept(); + void redirect(); }; void tst_QQMLTypeLoader::testLoadComplete() @@ -410,6 +412,22 @@ void tst_QQMLTypeLoader::intercept() QVERIFY(factory.loadedFiles.contains(QLatin1String(QT_TESTCASE_BUILDDIR) + "/Slow/qmldir")); } +void tst_QQMLTypeLoader::redirect() +{ + TestHTTPServer server; + QVERIFY2(server.listen(), qPrintable(server.errorString())); + QVERIFY(server.serveDirectory(dataDirectory())); + server.addRedirect("Base.qml", server.urlString("/redirected/Redirected.qml")); + + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(server.urlString("/Load.qml"), QQmlComponent::Asynchronous); + QTRY_VERIFY2(component.isReady(), qPrintable(component.errorString())); + + QObject *object = component.create(); + QTRY_COMPARE(object->property("xy").toInt(), 323232); +} + QTEST_MAIN(tst_QQMLTypeLoader) #include "tst_qqmltypeloader.moc" diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro index 3a20e94741..0352561e03 100644 --- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro +++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.pro @@ -3,7 +3,12 @@ TARGET = tst_qqmltypeloader QT += qml testlib qml-private quick macx:CONFIG -= app_bundle -SOURCES += tst_qqmltypeloader.cpp +SOURCES += \ + tst_qqmltypeloader.cpp \ + ../../shared/testhttpserver.cpp + +HEADERS += \ + ../../shared/testhttpserver.h include (../../shared/util.pri) diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp index 8d8c915e39..4b096f9c3a 100644 --- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp +++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp @@ -211,7 +211,7 @@ void tst_MptaInterop::touchesThenPinch() pinchStoleGrab = i; } qCDebug(lcPointerTests) << "pinch started after" << pinchStoleGrab << "moves; ended with scale" << pinch->scale() << "rot" << pinch->rotation(); - QTRY_VERIFY(pinch->rotation() > 8); + QTRY_VERIFY(pinch->rotation() > 4); QVERIFY(pinch->scale() > 1); // Press one more point (pinkie finger) diff --git a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp index 3e5a054cc7..8026bafb9e 100644 --- a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp +++ b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp @@ -67,6 +67,7 @@ private slots: void progressAndStatusChanges(); void playingAndPausedChanges(); void noCaching(); + void sourceChangesOnFrameChanged(); }; void tst_qquickanimatedimage::cleanup() @@ -590,6 +591,33 @@ void tst_qquickanimatedimage::noCaching() } } +void tst_qquickanimatedimage::sourceChangesOnFrameChanged() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("colors.qml")); + QVector<QQuickAnimatedImage*> images; + + // Run multiple animations in parallel, this should be fast + for (int loops = 0; loops < 25; ++loops) { + QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create()); + + // QTBUG-67427: this should not produce a segfault + QObject::connect(anim, + &QQuickAnimatedImage::frameChanged, + [this, anim]() { anim->setSource(testFileUrl("hearts.gif")); }); + + QVERIFY(anim); + QVERIFY(anim->isPlaying()); + + images.append(anim); + } + + for (auto *anim : images) + QTRY_COMPARE(anim->source(), testFileUrl("hearts.gif")); + + qDeleteAll(images); +} + QTEST_MAIN(tst_qquickanimatedimage) #include "tst_qquickanimatedimage.moc" diff --git a/tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro b/tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro index 81c73be831..85f71bb605 100644 --- a/tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro +++ b/tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro @@ -11,4 +11,4 @@ TESTDATA = data/* QT += core-private gui-private qml-private quick-private network testlib OTHER_FILES += \ - data/largeAnimation.qml + $$files(data/*.qml) diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml b/tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml index 00a12f2edc..7c87d896fb 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml @@ -33,7 +33,7 @@ CanvasTestCase { //comparePixel(ctx, 75,25, 63,63,191,255,3); ctx.reset(); - var g = ctx.createLinearGradient(0, 0, 100, 0); + g = ctx.createLinearGradient(0, 0, 100, 0); g.addColorStop(0, '#ff0'); g.addColorStop(1, '#00f'); ctx.fillStyle = g; @@ -44,7 +44,7 @@ CanvasTestCase { ctx.reset(); - var g = ctx.createLinearGradient(0, 0, 100, 0); + g = ctx.createLinearGradient(0, 0, 100, 0); g.addColorStop(0, 'rgba(255,255,0, 0)'); g.addColorStop(1, 'rgba(0,0,255, 1)'); ctx.fillStyle = g; @@ -55,7 +55,7 @@ CanvasTestCase { ctx.reset(); canvas.width = 200; - var g = ctx.createLinearGradient(0, 0, 200, 0); + g = ctx.createLinearGradient(0, 0, 200, 0); g.addColorStop(0, '#ff0'); g.addColorStop(0.5, '#0ff'); g.addColorStop(1, '#f0f'); @@ -69,7 +69,7 @@ CanvasTestCase { ctx.fillStyle = '#f00'; ctx.fillRect(0, 0, 100, 50); - var g = ctx.createLinearGradient(25, 0, 75, 0); + g = ctx.createLinearGradient(25, 0, 75, 0); g.addColorStop(0.4, '#0f0'); g.addColorStop(0.6, '#0f0'); @@ -82,7 +82,7 @@ CanvasTestCase { ctx.reset(); ctx.canvas.width = 200; - var g = ctx.createLinearGradient(0, 0, 200, 0); + g = ctx.createLinearGradient(0, 0, 200, 0); g.addColorStop(0, '#f00'); g.addColorStop(0, '#ff0'); g.addColorStop(0.25, '#00f'); @@ -110,7 +110,7 @@ CanvasTestCase { ctx.canvas.width = 100; ctx.reset(); - var g = ctx.createLinearGradient(0, 0, 100, 0); + g = ctx.createLinearGradient(0, 0, 100, 0); var ps = [ 0, 1/10, 1/4, 1/3, 1/2, 3/4, 1 ]; for (var p = 0; p < ps.length; ++p) { @@ -129,7 +129,7 @@ CanvasTestCase { ctx.reset(); - var g = ctx.createLinearGradient(0, 0, 100, 0); + g = ctx.createLinearGradient(0, 0, 100, 0); g.addColorStop(0, '#0f0'); g.addColorStop(1, '#0f0'); ctx.fillStyle = g; @@ -139,7 +139,7 @@ CanvasTestCase { ctx.reset(); - var g = ctx.createLinearGradient(0, 0, 0, 50); + g = ctx.createLinearGradient(0, 0, 0, 50); g.addColorStop(0, '#ff0'); g.addColorStop(1, '#00f'); ctx.fillStyle = g; @@ -154,7 +154,7 @@ CanvasTestCase { ctx.fillStyle = '#0f0'; ctx.fillRect(0, 0, 100, 50); - var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction) + g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction) g.addColorStop(0, '#f00'); g.addColorStop(1, '#f00'); ctx.fillStyle = g; @@ -278,7 +278,7 @@ CanvasTestCase { //comparePixel(ctx, 98,48, 0,255,0,255); ctx.reset(); - var tol = 1; // tolerance to avoid antialiasing artifacts + tol = 1; // tolerance to avoid antialiasing artifacts ctx.fillStyle = '#0f0'; ctx.fillRect(0, 0, 100, 50); @@ -410,243 +410,243 @@ CanvasTestCase { ctx.reset(); try { var err = false; ctx.createRadialGradient(0, 0, -0.1, 0, 0, 1); - } catch (e) { if (e.code != DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: ctx.createRadialGradient(0, 0, -0.1, 0, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: ctx.createRadialGradient(0, 0, -0.1, 0, 0, 1)"); } + try { err = false; ctx.createRadialGradient(0, 0, 1, 0, 0, -0.1); - } catch (e) { if (e.code != DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: ctx.createRadialGradient(0, 0, 1, 0, 0, -0.1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: ctx.createRadialGradient(0, 0, 1, 0, 0, -0.1)"); } + try { err = false; ctx.createRadialGradient(0, 0, -0.1, 0, 0, -0.1); - } catch (e) { if (e.code != DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: ctx.createRadialGradient(0, 0, -0.1, 0, 0, -0.1)"); } + } catch (e) { if (e.code !== DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: ctx.createRadialGradient(0, 0, -0.1, 0, 0, -0.1)"); } ctx.reset(); - try { var err = false; + try { err = false; ctx.createRadialGradient(Infinity, 0, 1, 0, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, 0, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, 0, 0, 1)"); } + try { err = false; ctx.createRadialGradient(-Infinity, 0, 1, 0, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(-Infinity, 0, 1, 0, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(-Infinity, 0, 1, 0, 0, 1)"); } + try { err = false; ctx.createRadialGradient(NaN, 0, 1, 0, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(NaN, 0, 1, 0, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(NaN, 0, 1, 0, 0, 1)"); } + try { err = false; ctx.createRadialGradient(0, Infinity, 1, 0, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, 0, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, 0, 0, 1)"); } + try { err = false; ctx.createRadialGradient(0, -Infinity, 1, 0, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, -Infinity, 1, 0, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, -Infinity, 1, 0, 0, 1)"); } + try { err = false; ctx.createRadialGradient(0, NaN, 1, 0, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, NaN, 1, 0, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, NaN, 1, 0, 0, 1)"); } + try { err = false; ctx.createRadialGradient(0, 0, Infinity, 0, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, 0, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, 0, 0, 1)"); } + try { err = false; ctx.createRadialGradient(0, 0, -Infinity, 0, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, -Infinity, 0, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, -Infinity, 0, 0, 1)"); } + try { err = false; ctx.createRadialGradient(0, 0, NaN, 0, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, NaN, 0, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, NaN, 0, 0, 1)"); } + try { err = false; ctx.createRadialGradient(0, 0, 1, Infinity, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, Infinity, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, Infinity, 0, 1)"); } + try { err = false; ctx.createRadialGradient(0, 0, 1, -Infinity, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, -Infinity, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, -Infinity, 0, 1)"); } + try { err = false; ctx.createRadialGradient(0, 0, 1, NaN, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, NaN, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, NaN, 0, 1)"); } + try { err = false; ctx.createRadialGradient(0, 0, 1, 0, Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(0, 0, 1, 0, -Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, -Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, -Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(0, 0, 1, 0, NaN, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, NaN, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, NaN, 1)"); } + try { err = false; ctx.createRadialGradient(0, 0, 1, 0, 0, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, 0, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, 0, Infinity)"); } + try { err = false; ctx.createRadialGradient(0, 0, 1, 0, 0, -Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, 0, -Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, 0, -Infinity)"); } + try { err = false; ctx.createRadialGradient(0, 0, 1, 0, 0, NaN); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, 0, NaN)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, 0, NaN)"); } + try { err = false; ctx.createRadialGradient(Infinity, Infinity, 1, 0, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, 0, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, 0, 0, 1)"); } + try { err = false; ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, 0, 1)"); } + try { err = false; ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, 0, 1)"); } + try { err = false; ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, Infinity, Infinity)"); } + try { err = false; ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, 0, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, 0, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, 0, Infinity)"); } + try { err = false; ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, Infinity, Infinity)"); } + try { err = false; ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, 0, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, 0, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, 0, Infinity)"); } + try { err = false; ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, 0, 1)"); } + try { err = false; ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, Infinity, Infinity)"); } + try { err = false; ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, 0, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, 0, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, 0, Infinity)"); } + try { err = false; ctx.createRadialGradient(Infinity, Infinity, 1, 0, Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, 0, Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, 0, Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(Infinity, Infinity, 1, 0, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, 0, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, 0, Infinity, Infinity)"); } + try { err = false; ctx.createRadialGradient(Infinity, Infinity, 1, 0, 0, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, 0, 0, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, Infinity, 1, 0, 0, Infinity)"); } + try { err = false; ctx.createRadialGradient(Infinity, 0, Infinity, 0, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, 0, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, 0, 0, 1)"); } + try { err = false; ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, 0, 1)"); } + try { err = false; ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, Infinity, Infinity)"); } + try { err = false; ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, 0, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, 0, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, 0, Infinity)"); } + try { err = false; ctx.createRadialGradient(Infinity, 0, Infinity, 0, Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, 0, Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, 0, Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(Infinity, 0, Infinity, 0, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, 0, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, 0, Infinity, Infinity)"); } + try { err = false; ctx.createRadialGradient(Infinity, 0, Infinity, 0, 0, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, 0, 0, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, Infinity, 0, 0, Infinity)"); } + try { err = false; ctx.createRadialGradient(Infinity, 0, 1, Infinity, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, Infinity, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, Infinity, 0, 1)"); } + try { err = false; ctx.createRadialGradient(Infinity, 0, 1, Infinity, Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, Infinity, Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, Infinity, Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(Infinity, 0, 1, Infinity, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, Infinity, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, Infinity, Infinity, Infinity)"); } + try { err = false; ctx.createRadialGradient(Infinity, 0, 1, Infinity, 0, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, Infinity, 0, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, Infinity, 0, Infinity)"); } + try { err = false; ctx.createRadialGradient(Infinity, 0, 1, 0, Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, 0, Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, 0, Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(Infinity, 0, 1, 0, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, 0, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, 0, Infinity, Infinity)"); } + try { err = false; ctx.createRadialGradient(Infinity, 0, 1, 0, 0, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, 0, 0, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(Infinity, 0, 1, 0, 0, Infinity)"); } + try { err = false; ctx.createRadialGradient(0, Infinity, Infinity, 0, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, 0, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, 0, 0, 1)"); } + try { err = false; ctx.createRadialGradient(0, Infinity, Infinity, Infinity, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, Infinity, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, Infinity, 0, 1)"); } + try { err = false; ctx.createRadialGradient(0, Infinity, Infinity, Infinity, Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, Infinity, Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, Infinity, Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(0, Infinity, Infinity, Infinity, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, Infinity, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, Infinity, Infinity, Infinity)"); } + try { err = false; ctx.createRadialGradient(0, Infinity, Infinity, Infinity, 0, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, Infinity, 0, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, Infinity, 0, Infinity)"); } + try { err = false; ctx.createRadialGradient(0, Infinity, Infinity, 0, Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, 0, Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, 0, Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(0, Infinity, Infinity, 0, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, 0, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, 0, Infinity, Infinity)"); } + try { err = false; ctx.createRadialGradient(0, Infinity, Infinity, 0, 0, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, 0, 0, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, Infinity, 0, 0, Infinity)"); } + try { err = false; ctx.createRadialGradient(0, Infinity, 1, Infinity, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, Infinity, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, Infinity, 0, 1)"); } + try { err = false; ctx.createRadialGradient(0, Infinity, 1, Infinity, Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, Infinity, Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, Infinity, Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(0, Infinity, 1, Infinity, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, Infinity, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, Infinity, Infinity, Infinity)"); } + try { err = false; ctx.createRadialGradient(0, Infinity, 1, Infinity, 0, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, Infinity, 0, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, Infinity, 0, Infinity)"); } + try { err = false; ctx.createRadialGradient(0, Infinity, 1, 0, Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, 0, Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, 0, Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(0, Infinity, 1, 0, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, 0, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, 0, Infinity, Infinity)"); } + try { err = false; ctx.createRadialGradient(0, Infinity, 1, 0, 0, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, 0, 0, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, Infinity, 1, 0, 0, Infinity)"); } + try { err = false; ctx.createRadialGradient(0, 0, Infinity, Infinity, 0, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, Infinity, 0, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, Infinity, 0, 1)"); } + try { err = false; ctx.createRadialGradient(0, 0, Infinity, Infinity, Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, Infinity, Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, Infinity, Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(0, 0, Infinity, Infinity, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, Infinity, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, Infinity, Infinity, Infinity)"); } + try { err = false; ctx.createRadialGradient(0, 0, Infinity, Infinity, 0, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, Infinity, 0, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, Infinity, 0, Infinity)"); } + try { err = false; ctx.createRadialGradient(0, 0, Infinity, 0, Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, 0, Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, 0, Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(0, 0, Infinity, 0, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, 0, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, 0, Infinity, Infinity)"); } + try { err = false; ctx.createRadialGradient(0, 0, Infinity, 0, 0, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, 0, 0, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, Infinity, 0, 0, Infinity)"); } + try { err = false; ctx.createRadialGradient(0, 0, 1, Infinity, Infinity, 1); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, Infinity, Infinity, 1)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, Infinity, Infinity, 1)"); } + try { err = false; ctx.createRadialGradient(0, 0, 1, Infinity, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, Infinity, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, Infinity, Infinity, Infinity)"); } + try { err = false; ctx.createRadialGradient(0, 0, 1, Infinity, 0, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, Infinity, 0, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, Infinity, 0, Infinity)"); } + try { err = false; ctx.createRadialGradient(0, 0, 1, 0, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, Infinity, Infinity)"); } + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createRadialGradient(0, 0, 1, 0, Infinity, Infinity)"); } ctx.reset(); @@ -792,73 +792,73 @@ CanvasTestCase { ctx.reset(); try { var err = false; ctx.createLinearGradient(Infinity, 0, 1, 0); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, 0, 1, 0)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, 0, 1, 0)"); } + try { err = false; ctx.createLinearGradient(-Infinity, 0, 1, 0); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(-Infinity, 0, 1, 0)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(-Infinity, 0, 1, 0)"); } + try { err = false; ctx.createLinearGradient(NaN, 0, 1, 0); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(NaN, 0, 1, 0)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(NaN, 0, 1, 0)"); } + try { err = false; ctx.createLinearGradient(0, Infinity, 1, 0); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, Infinity, 1, 0)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, Infinity, 1, 0)"); } + try { err = false; ctx.createLinearGradient(0, -Infinity, 1, 0); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, -Infinity, 1, 0)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, -Infinity, 1, 0)"); } + try { err = false; ctx.createLinearGradient(0, NaN, 1, 0); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, NaN, 1, 0)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, NaN, 1, 0)"); } + try { err = false; ctx.createLinearGradient(0, 0, Infinity, 0); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, Infinity, 0)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, Infinity, 0)"); } + try { err = false; ctx.createLinearGradient(0, 0, -Infinity, 0); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, -Infinity, 0)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, -Infinity, 0)"); } + try { err = false; ctx.createLinearGradient(0, 0, NaN, 0); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, NaN, 0)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, NaN, 0)"); } + try { err = false; ctx.createLinearGradient(0, 0, 1, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, 1, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, 1, Infinity)"); } + try { err = false; ctx.createLinearGradient(0, 0, 1, -Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, 1, -Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, 1, -Infinity)"); } + try { err = false; ctx.createLinearGradient(0, 0, 1, NaN); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, 1, NaN)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, 1, NaN)"); } + try { err = false; ctx.createLinearGradient(Infinity, Infinity, 1, 0); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, Infinity, 1, 0)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, Infinity, 1, 0)"); } + try { err = false; ctx.createLinearGradient(Infinity, Infinity, Infinity, 0); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, Infinity, Infinity, 0)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, Infinity, Infinity, 0)"); } + try { err = false; ctx.createLinearGradient(Infinity, Infinity, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, Infinity, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, Infinity, Infinity, Infinity)"); } + try { err = false; ctx.createLinearGradient(Infinity, Infinity, 1, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, Infinity, 1, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, Infinity, 1, Infinity)"); } + try { err = false; ctx.createLinearGradient(Infinity, 0, Infinity, 0); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, 0, Infinity, 0)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, 0, Infinity, 0)"); } + try { err = false; ctx.createLinearGradient(Infinity, 0, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, 0, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, 0, Infinity, Infinity)"); } + try { err = false; ctx.createLinearGradient(Infinity, 0, 1, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, 0, 1, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(Infinity, 0, 1, Infinity)"); } + try { err = false; ctx.createLinearGradient(0, Infinity, Infinity, 0); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, Infinity, Infinity, 0)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, Infinity, Infinity, 0)"); } + try { err = false; ctx.createLinearGradient(0, Infinity, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, Infinity, Infinity, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, Infinity, Infinity, Infinity)"); } + try { err = false; ctx.createLinearGradient(0, Infinity, 1, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, Infinity, 1, Infinity)"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, Infinity, 1, Infinity)"); } + try { err = false; ctx.createLinearGradient(0, 0, Infinity, Infinity); - } catch (e) { if (e.code != DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, Infinity, Infinity)"); } + } catch (e) { if (e.code !== DOMException.NOT_SUPPORTED_ERR) fail("Failed assertion: expected exception of type NOT_SUPPORTED_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type NOT_SUPPORTED_ERR: ctx.createLinearGradient(0, 0, Infinity, Infinity)"); } ctx.reset(); var g = ctx.createLinearGradient(0, 0, 200, 0); @@ -918,29 +918,29 @@ CanvasTestCase { var g = ctx.createLinearGradient(0, 0, 100, 0); try { var err = false; g.addColorStop(0, ""); - } catch (e) { if (e.code != DOMException.SYNTAX_ERR) fail("Failed assertion: expected exception of type SYNTAX_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type SYNTAX_ERR: g.addColorStop(0, \"\")"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.SYNTAX_ERR) fail("Failed assertion: expected exception of type SYNTAX_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type SYNTAX_ERR: g.addColorStop(0, \"\")"); } + try { err = false; g.addColorStop(0, 'undefined'); - } catch (e) { if (e.code != DOMException.SYNTAX_ERR) fail("Failed assertion: expected exception of type SYNTAX_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type SYNTAX_ERR: g.addColorStop(0, 'undefined')"); } + } catch (e) { if (e.code !== DOMException.SYNTAX_ERR) fail("Failed assertion: expected exception of type SYNTAX_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type SYNTAX_ERR: g.addColorStop(0, 'undefined')"); } ctx.reset(); g = ctx.createLinearGradient(0, 0, 100, 0); - try { var err = false; + try { err = false; g.addColorStop(-1, '#000'); - } catch (e) { if (e.code != DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(-1, '#000')"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(-1, '#000')"); } + try { err = false; g.addColorStop(2, '#000'); - } catch (e) { if (e.code != DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(2, '#000')"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(2, '#000')"); } + try { err = false; g.addColorStop(Infinity, '#000'); - } catch (e) { if (e.code != DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(Infinity, '#000')"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(Infinity, '#000')"); } + try { err = false; g.addColorStop(-Infinity, '#000'); - } catch (e) { if (e.code != DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(-Infinity, '#000')"); } - try { var err = false; + } catch (e) { if (e.code !== DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(-Infinity, '#000')"); } + try { err = false; g.addColorStop(NaN, '#000'); - } catch (e) { if (e.code != DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(NaN, '#000')"); } + } catch (e) { if (e.code !== DOMException.INDEX_SIZE_ERR) fail("Failed assertion: expected exception of type INDEX_SIZE_ERR, got: "+e.message); err = true; } finally { verify(err, "should throw exception of type INDEX_SIZE_ERR: g.addColorStop(NaN, '#000')"); } ctx.reset(); diff --git a/tests/auto/quick/qquickitem/BLACKLIST b/tests/auto/quick/qquickitem/BLACKLIST index d94a3ef102..85c4df4feb 100644 --- a/tests/auto/quick/qquickitem/BLACKLIST +++ b/tests/auto/quick/qquickitem/BLACKLIST @@ -1,2 +1,5 @@ [contains:hollow square: testing points inside] xcb + +[qtBug60123] +offscreen diff --git a/tests/auto/quick/qquickitem2/data/mapCoordinates.qml b/tests/auto/quick/qquickitem2/data/mapCoordinates.qml index b410b445c5..596dedab90 100644 --- a/tests/auto/quick/qquickitem2/data/mapCoordinates.qml +++ b/tests/auto/quick/qquickitem2/data/mapCoordinates.qml @@ -39,6 +39,11 @@ Item { Item { id: itemB; objectName: "itemB"; x: 100; y: 100 } } + Component { + id: itemComponent + Item { x: 150; y: 150 } + } + function mapAToB(x, y) { var pos = itemA.mapToItem(itemB, x, y) return Qt.point(pos.x, pos.y) @@ -69,6 +74,18 @@ Item { return Qt.point(pos.x, pos.y) } + function mapOrphanToGlobal(x, y) { + var obj = itemComponent.createObject(null); + var pos = obj.mapToGlobal(x, y) + return Qt.point(pos.x, pos.y) + } + + function mapOrphanFromGlobal(x, y) { + var obj = itemComponent.createObject(null); + var pos = obj.mapFromGlobal(x, y) + return Qt.point(pos.x, pos.y) + } + function checkMapAToInvalid(x, y) { try { itemA.mapToItem(1122, x, y) diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp index 0f4850d4a7..f0f5873ace 100644 --- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp @@ -2364,6 +2364,16 @@ void tst_QQuickItem::mapCoordinates() Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y))); QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromGlobal(QPointF(x, y))); + // for orphans we are primarily testing that we don't crash. + // when orphaned the final position is the original position of the item translated by x,y + QVERIFY(QMetaObject::invokeMethod(root, "mapOrphanToGlobal", + Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y))); + QCOMPARE(result.value<QPointF>(), QPointF(150,150) + QPointF(x, y)); + + QVERIFY(QMetaObject::invokeMethod(root, "mapOrphanFromGlobal", + Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y))); + QCOMPARE(result.value<QPointF>(), -QPointF(150,150) + QPointF(x, y)); + QString warning1 = testFileUrl("mapCoordinates.qml").toString() + ":35:5: QML Item: mapToItem() given argument \"1122\" which is neither null nor an Item"; QString warning2 = testFileUrl("mapCoordinates.qml").toString() + ":35:5: QML Item: mapFromItem() given argument \"1122\" which is neither null nor an Item"; diff --git a/tests/auto/quick/qquicklistview/data/snapToItemWithSpacing.qml b/tests/auto/quick/qquicklistview/data/snapToItemWithSpacing.qml new file mode 100644 index 0000000000..50b5abb206 --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/snapToItemWithSpacing.qml @@ -0,0 +1,18 @@ +import QtQuick 2.0 + +ListView { + width: 100 + height: 300 + snapMode: ListView.SnapToItem + spacing: 100 + model: 10 + delegate: Rectangle { + height: 100 + width: 100 + color: "blue" + Text { + anchors.centerIn: parent + text: index + } + } +} diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index 8bc5575e34..c1daddb561 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -176,6 +176,7 @@ private slots: void creationContext(); void snapToItem_data(); void snapToItem(); + void snapToItemWithSpacing_QTBUG_59852(); void snapOneItemResize_QTBUG_43555(); void snapOneItem_data(); void snapOneItem(); @@ -5197,6 +5198,31 @@ void tst_QQuickListView::snapToItem() releaseView(window); } +void tst_QQuickListView::snapToItemWithSpacing_QTBUG_59852() +{ + QQuickView *window = getView(); + + window->setSource(testFileUrl("snapToItemWithSpacing.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + auto *listView = qobject_cast<QQuickListView*>(window->rootObject()); + QVERIFY(listView); + + QTRY_COMPARE(QQuickItemPrivate::get(listView)->polishScheduled, false); + + // each item in the list is 100 pixels tall, and the spacing is 100 + + listView->setContentY(110); // this is right below the first item + listView->returnToBounds(); + QCOMPARE(listView->contentY(), 200); // the position of the second item + + listView->setContentY(60); // this is right below the middle of the first item + listView->returnToBounds(); + QCOMPARE(listView->contentY(), 0); // it's farther to go to the next item, so snaps to the first + + releaseView(window); +} void tst_QQuickListView::snapOneItemResize_QTBUG_43555() { @@ -8666,8 +8692,6 @@ void tst_QQuickListView::QTBUG_34576_velocityZero() QQuickView *window = new QQuickView(nullptr); window->setGeometry(0,0,240,320); - QQmlContext *ctxt = window->rootContext(); - QString filename(testFile("qtbug34576.qml")); window->setSource(QUrl::fromLocalFile(filename)); window->show(); diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp index 5f7f35b5d7..4211d08393 100644 --- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp +++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp @@ -2462,9 +2462,11 @@ static void verify_offsets(QQuickPathView *pathview, int toidx, qreal fromoffset QTest::qWait(100); first = pathview->offset(); while (1) { + if (first == 0) + first = pathview->offset(); QTest::qWait(10); // highlightMoveDuration: 1000 second = pathview->offset(); - if (!started && second != first) { // animation started + if (!started && first != 0 && second != first) { // animation started started = true; break; } diff --git a/tests/auto/quick/qquickwindow/BLACKLIST b/tests/auto/quick/qquickwindow/BLACKLIST index 6c2671ad9e..bb9f403188 100644 --- a/tests/auto/quick/qquickwindow/BLACKLIST +++ b/tests/auto/quick/qquickwindow/BLACKLIST @@ -1,6 +1,3 @@ # QTBUG-62177 [attachedProperty] osx -# QTBUG-53916 -[touchEvent_propagation:hide item] -ubuntu diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index cd3486f95f..042908bf0c 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -179,6 +179,7 @@ public: bool acceptTouchEvents; bool acceptMouseEvents; + bool grabOnRelease = false; TouchEventData lastEvent; int mousePressCount; int mouseMoveCount; @@ -248,6 +249,10 @@ public: case QEvent::MouseButtonPress: mousePressCount = ++mousePressNum; break; + case QEvent::MouseButtonRelease: + if (grabOnRelease) + grabMouse(); + break; case QEvent::MouseMove: mouseMoveCount = ++mouseMoveNum; break; @@ -468,6 +473,7 @@ private slots: void testChildMouseEventFilter(); void testChildMouseEventFilter_data(); + void cleanupGrabsOnRelease(); private: QTouchDevice *touchDevice; @@ -3514,6 +3520,41 @@ void tst_qquickwindow::testChildMouseEventFilter() QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, mousePos); } +void tst_qquickwindow::cleanupGrabsOnRelease() +{ + TestTouchItem::clearMouseEventCounters(); + + QQuickWindow *window = new QQuickWindow; + QScopedPointer<QQuickWindow> cleanup(window); + window->resize(250, 250); + window->setPosition(100, 100); + window->setTitle(QTest::currentTestFunction()); + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + TestTouchItem *parent = new TestTouchItem(window->contentItem()); + parent->setObjectName("parent"); + parent->setSize(QSizeF(150, 150)); + parent->acceptMouseEvents = true; + parent->grabOnRelease = true; + + TestTouchItem *child = new TestTouchItem(parent); + child->setObjectName("child"); + child->setSize(QSizeF(100, 100)); + child->acceptMouseEvents = true; + + QPoint pos(80, 80); + + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, pos); + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, pos); + // There is an explicit parent->grabMouse on release(!). This means grab changes from child + // to parent: + // This will emit two ungrab events: + // 1. One for the child (due to the explicit call to parent->grabMouse()) + // 2. One for the parent (since the mouse button was finally released) + QCOMPARE(child->mouseUngrabEventCount, 1); + QCOMPARE(parent->mouseUngrabEventCount, 1); +} QTEST_MAIN(tst_qquickwindow) diff --git a/tests/auto/shared/util.cpp b/tests/auto/shared/util.cpp index 96beb51612..189398f0c2 100644 --- a/tests/auto/shared/util.cpp +++ b/tests/auto/shared/util.cpp @@ -28,11 +28,6 @@ #include "util.h" -#include <QtQml/QQmlComponent> -#include <QtQml/QQmlError> -#include <QtQml/QQmlContext> -#include <QtQml/QQmlEngine> -#include <QtCore/QTextStream> #include <QtCore/QDebug> #include <QtCore/QMutexLocker> @@ -72,31 +67,6 @@ QString QQmlDataTest::testFile(const QString &fileName) const return result; } -QByteArray QQmlDataTest::msgComponentError(const QQmlComponent &c, - const QQmlEngine *engine /* = 0 */) -{ - QString result; - const QList<QQmlError> errors = c.errors(); - QTextStream str(&result); - str << "Component '" << c.url().toString() << "' has " << errors.size() - << " errors: '"; - for (int i = 0; i < errors.size(); ++i) { - if (i) - str << ", '"; - str << errors.at(i).toString() << '\''; - - } - if (!engine) - if (QQmlContext *context = c.creationContext()) - engine = context->engine(); - if (engine) { - str << " Import paths: (" << engine->importPathList().join(QStringLiteral(", ")) - << ") Plugin paths: (" << engine->pluginPathList().join(QStringLiteral(", ")) - << ')'; - } - return result.toLocal8Bit(); -} - Q_GLOBAL_STATIC(QMutex, qQmlTestMessageHandlerMutex) QQmlTestMessageHandler *QQmlTestMessageHandler::m_instance = 0; diff --git a/tests/auto/shared/util.h b/tests/auto/shared/util.h index 33d7cbd1d0..6f3f0a06a8 100644 --- a/tests/auto/shared/util.h +++ b/tests/auto/shared/util.h @@ -35,9 +35,6 @@ #include <QtCore/QStringList> #include <QtTest/QTest> -QT_FORWARD_DECLARE_CLASS(QQmlComponent) -QT_FORWARD_DECLARE_CLASS(QQmlEngine) - /* Base class for tests with data that are located in a "data" subfolder. */ class QQmlDataTest : public QObject @@ -61,9 +58,6 @@ public: static inline QQmlDataTest *instance() { return m_instance; } - static QByteArray msgComponentError(const QQmlComponent &, - const QQmlEngine *engine = 0); - public slots: virtual void initTestCase(); diff --git a/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp index 9c97ef7694..adc9def590 100644 --- a/tools/qmlcachegen/qmlcachegen.cpp +++ b/tools/qmlcachegen/qmlcachegen.cpp @@ -261,7 +261,7 @@ static bool compileJSFile(const QString &inputFileName, const QString &inputFile } QQmlJS::Engine *engine = &irDocument.jsParserEngine; - QmlIR::ScriptDirectivesCollector directivesCollector(engine, &irDocument.jsGenerator); + QmlIR::ScriptDirectivesCollector directivesCollector(&irDocument); QQmlJS::Directives *oldDirs = engine->directives(); engine->setDirectives(&directivesCollector); diff --git a/tools/qmlprofiler/qmlprofiler.pro b/tools/qmlprofiler/qmlprofiler.pro index a2522e9267..28e316b23a 100644 --- a/tools/qmlprofiler/qmlprofiler.pro +++ b/tools/qmlprofiler/qmlprofiler.pro @@ -1,4 +1,4 @@ -QT = qml-private network core qmldebug-private +QT = network core qmldebug-private CONFIG += no_import_scan SOURCES += main.cpp \ diff --git a/tools/qmlprofiler/qmlprofilerapplication.cpp b/tools/qmlprofiler/qmlprofilerapplication.cpp index 3ab6741afa..0b63a91e5b 100644 --- a/tools/qmlprofiler/qmlprofilerapplication.cpp +++ b/tools/qmlprofiler/qmlprofilerapplication.cpp @@ -70,8 +70,7 @@ static const char *features[] = { "debugmessages" }; -Q_STATIC_ASSERT(sizeof(features) == - QQmlProfilerDefinitions::MaximumProfileFeature * sizeof(char *)); +Q_STATIC_ASSERT(sizeof(features) == MaximumProfileFeature * sizeof(char *)); QmlProfilerApplication::QmlProfilerApplication(int &argc, char **argv) : QCoreApplication(argc, argv), @@ -164,7 +163,7 @@ void QmlProfilerApplication::parseArguments() parser.addOption(record); QStringList featureList; - for (int i = 0; i < QQmlProfilerDefinitions::MaximumProfileFeature; ++i) + for (int i = 0; i < MaximumProfileFeature; ++i) featureList << QLatin1String(features[i]); QCommandLineOption include(QLatin1String("include"), diff --git a/tools/qmlprofiler/qmlprofilerclient.h b/tools/qmlprofiler/qmlprofilerclient.h index b9d8ce241f..30f4a51751 100644 --- a/tools/qmlprofiler/qmlprofilerclient.h +++ b/tools/qmlprofiler/qmlprofilerclient.h @@ -30,7 +30,7 @@ #define QMLPROFILERCLIENT_H #include <private/qqmlprofilerclient_p.h> -#include <private/qqmlprofilerdefinitions_p.h> +#include <private/qqmlprofilerclientdefinitions_p.h> #include <private/qqmlprofilereventlocation_p.h> class QmlProfilerData; diff --git a/tools/qmlprofiler/qmlprofilerdata.cpp b/tools/qmlprofiler/qmlprofilerdata.cpp index 32e03298da..d5662a0182 100644 --- a/tools/qmlprofiler/qmlprofilerdata.cpp +++ b/tools/qmlprofiler/qmlprofilerdata.cpp @@ -50,8 +50,7 @@ static const char *RANGE_TYPE_STRINGS[] = { "Javascript" }; -Q_STATIC_ASSERT(sizeof(RANGE_TYPE_STRINGS) == - QQmlProfilerDefinitions::MaximumRangeType * sizeof(const char *)); +Q_STATIC_ASSERT(sizeof(RANGE_TYPE_STRINGS) == MaximumRangeType * sizeof(const char *)); static const char *MESSAGE_STRINGS[] = { "Event", @@ -66,8 +65,7 @@ static const char *MESSAGE_STRINGS[] = { "DebugMessage" }; -Q_STATIC_ASSERT(sizeof(MESSAGE_STRINGS) == - QQmlProfilerDefinitions::MaximumMessage * sizeof(const char *)); +Q_STATIC_ASSERT(sizeof(MESSAGE_STRINGS) == MaximumMessage * sizeof(const char *)); ///////////////////////////////////////////////////////////////// class QmlProfilerDataPrivate @@ -113,7 +111,7 @@ void QmlProfilerData::clear() setState(Empty); } -QString QmlProfilerData::qmlRangeTypeAsString(QQmlProfilerDefinitions::RangeType type) +QString QmlProfilerData::qmlRangeTypeAsString(RangeType type) { if (type * sizeof(char *) < sizeof(RANGE_TYPE_STRINGS)) return QLatin1String(RANGE_TYPE_STRINGS[type]); @@ -121,7 +119,7 @@ QString QmlProfilerData::qmlRangeTypeAsString(QQmlProfilerDefinitions::RangeType return QString::number(type); } -QString QmlProfilerData::qmlMessageAsString(QQmlProfilerDefinitions::Message type) +QString QmlProfilerData::qmlMessageAsString(Message type) { if (type * sizeof(char *) < sizeof(MESSAGE_STRINGS)) return QLatin1String(MESSAGE_STRINGS[type]); @@ -178,13 +176,13 @@ void QmlProfilerData::addEventType(const QQmlProfilerEventType &type) QString displayName; switch (type.message()) { - case QQmlProfilerDefinitions::Event: { + case Event: { switch (type.detailType()) { - case QQmlProfilerDefinitions::Mouse: - case QQmlProfilerDefinitions::Key: + case Mouse: + case Key: displayName = QString::fromLatin1("Input:%1").arg(type.detailType()); break; - case QQmlProfilerDefinitions::AnimationFrame: + case AnimationFrame: displayName = QString::fromLatin1("AnimationFrame"); break; default: @@ -192,29 +190,29 @@ void QmlProfilerData::addEventType(const QQmlProfilerEventType &type) } break; } - case QQmlProfilerDefinitions::RangeStart: - case QQmlProfilerDefinitions::RangeData: - case QQmlProfilerDefinitions::RangeLocation: - case QQmlProfilerDefinitions::RangeEnd: - case QQmlProfilerDefinitions::Complete: + case RangeStart: + case RangeData: + case RangeLocation: + case RangeEnd: + case Complete: Q_UNREACHABLE(); break; - case QQmlProfilerDefinitions::PixmapCacheEvent: { + case PixmapCacheEvent: { const QString filePath = QUrl(type.location().filename()).path(); displayName = filePath.midRef(filePath.lastIndexOf(QLatin1Char('/')) + 1) + QLatin1Char(':') + QString::number(type.detailType()); break; } - case QQmlProfilerDefinitions::SceneGraphFrame: + case SceneGraphFrame: displayName = QString::fromLatin1("SceneGraph:%1").arg(type.detailType()); break; - case QQmlProfilerDefinitions::MemoryAllocation: + case MemoryAllocation: displayName = QString::fromLatin1("MemoryAllocation:%1").arg(type.detailType()); break; - case QQmlProfilerDefinitions::DebugMessage: + case DebugMessage: displayName = QString::fromLatin1("DebugMessage:%1").arg(type.detailType()); break; - case QQmlProfilerDefinitions::MaximumMessage: { + case MaximumMessage: { const QQmlProfilerEventLocation eventLocation = type.location(); // generate hash if (eventLocation.filename().isEmpty()) { @@ -241,21 +239,21 @@ void QmlProfilerData::computeQmlTime() for (const QQmlProfilerEvent &event : qAsConst(d->events)) { const QQmlProfilerEventType &type = d->eventTypes.at(event.typeIndex()); - if (type.message() != QQmlProfilerDefinitions::MaximumMessage) + if (type.message() != MaximumMessage) continue; switch (type.rangeType()) { - case QQmlProfilerDefinitions::Compiling: - case QQmlProfilerDefinitions::Creating: - case QQmlProfilerDefinitions::Binding: - case QQmlProfilerDefinitions::HandlingSignal: - case QQmlProfilerDefinitions::Javascript: + case Compiling: + case Creating: + case Binding: + case HandlingSignal: + case Javascript: switch (event.rangeStage()) { - case QQmlProfilerDefinitions::RangeStart: + case RangeStart: if (level++ == 0) level0Start = event.timestamp(); break; - case QQmlProfilerDefinitions::RangeEnd: + case RangeEnd: if (--level == 0) d->qmlMeasuredTime += event.timestamp() - level0Start; break; @@ -430,8 +428,7 @@ bool QmlProfilerData::save(const QString &filename) if (!eventData.displayName().isEmpty()) stream.writeTextElement("displayname", eventData.displayName()); - stream.writeTextElement("type", - eventData.rangeType() == QQmlProfilerDefinitions::MaximumRangeType + stream.writeTextElement("type", eventData.rangeType() == MaximumRangeType ? qmlMessageAsString(eventData.message()) : qmlRangeTypeAsString(eventData.rangeType())); @@ -444,25 +441,25 @@ bool QmlProfilerData::save(const QString &filename) stream.writeTextElement("column", location.column()); if (!eventData.data().isEmpty()) stream.writeTextElement("details", eventData.data()); - if (eventData.rangeType() == QQmlProfilerDefinitions::Binding) + if (eventData.rangeType() == Binding) stream.writeTextElement("bindingType", eventData.detailType()); - else if (eventData.message() == QQmlProfilerDefinitions::Event) { + else if (eventData.message() == Event) { switch (eventData.detailType()) { - case QQmlProfilerDefinitions::AnimationFrame: + case AnimationFrame: stream.writeTextElement("animationFrame", eventData.detailType()); break; - case QQmlProfilerDefinitions::Key: + case Key: stream.writeTextElement("keyEvent", eventData.detailType()); break; - case QQmlProfilerDefinitions::Mouse: + case Mouse: stream.writeTextElement("mouseEvent", eventData.detailType()); break; } - } else if (eventData.message() == QQmlProfilerDefinitions::PixmapCacheEvent) + } else if (eventData.message() == PixmapCacheEvent) stream.writeTextElement("cacheEventType", eventData.detailType()); - else if (eventData.message() == QQmlProfilerDefinitions::SceneGraphFrame) + else if (eventData.message() == SceneGraphFrame) stream.writeTextElement("sgEventType", eventData.detailType()); - else if (eventData.message() == QQmlProfilerDefinitions::MemoryAllocation) + else if (eventData.message() == MemoryAllocation) stream.writeTextElement("memoryEventType", eventData.detailType()); stream.writeEndElement(); } @@ -477,50 +474,49 @@ bool QmlProfilerData::save(const QString &filename) if (duration != 0) stream.writeAttribute("duration", duration); stream.writeAttribute("eventIndex", event.typeIndex()); - if (type.message() == QQmlProfilerDefinitions::Event) { - if (type.detailType() == QQmlProfilerDefinitions::AnimationFrame) { + if (type.message() == Event) { + if (type.detailType() == AnimationFrame) { // special: animation frame stream.writeAttribute("framerate", event, 0); stream.writeAttribute("animationcount", event, 1); stream.writeAttribute("thread", event, 2); - } else if (type.detailType() == QQmlProfilerDefinitions::Key || - type.detailType() == QQmlProfilerDefinitions::Mouse) { + } else if (type.detailType() == Key || type.detailType() == Mouse) { // numerical value here, to keep the format a bit more compact stream.writeAttribute("type", event, 0); stream.writeAttribute("data1", event, 1); stream.writeAttribute("data2", event, 2); } - } else if (type.message() == QQmlProfilerDefinitions::PixmapCacheEvent) { + } else if (type.message() == PixmapCacheEvent) { // special: pixmap cache event - if (type.detailType() == QQmlProfilerDefinitions::PixmapSizeKnown) { + if (type.detailType() == PixmapSizeKnown) { stream.writeAttribute("width", event, 0); stream.writeAttribute("height", event, 1); - } else if (type.detailType() == QQmlProfilerDefinitions::PixmapReferenceCountChanged - || type.detailType() == QQmlProfilerDefinitions::PixmapCacheCountChanged) { + } else if (type.detailType() == PixmapReferenceCountChanged + || type.detailType() == PixmapCacheCountChanged) { stream.writeAttribute("refCount", event, 1); } - } else if (type.message() == QQmlProfilerDefinitions::SceneGraphFrame) { + } else if (type.message() == SceneGraphFrame) { stream.writeAttribute("timing1", event, 0, false); stream.writeAttribute("timing2", event, 1, false); stream.writeAttribute("timing3", event, 2, false); stream.writeAttribute("timing4", event, 3, false); stream.writeAttribute("timing5", event, 4, false); - } else if (type.message() == QQmlProfilerDefinitions::MemoryAllocation) { + } else if (type.message() == MemoryAllocation) { stream.writeAttribute("amount", event, 0); } stream.writeEndElement(); }; QQueue<QQmlProfilerEvent> pointEvents; - QQueue<QQmlProfilerEvent> rangeStarts[QQmlProfilerDefinitions::MaximumRangeType]; - QStack<qint64> rangeEnds[QQmlProfilerDefinitions::MaximumRangeType]; + QQueue<QQmlProfilerEvent> rangeStarts[MaximumRangeType]; + QStack<qint64> rangeEnds[MaximumRangeType]; int level = 0; auto sendPending = [&]() { forever { - int minimum = QQmlProfilerDefinitions::MaximumRangeType; + int minimum = MaximumRangeType; qint64 minimumTime = std::numeric_limits<qint64>::max(); - for (int i = 0; i < QQmlProfilerDefinitions::MaximumRangeType; ++i) { + for (int i = 0; i < MaximumRangeType; ++i) { const QQueue<QQmlProfilerEvent> &starts = rangeStarts[i]; if (starts.isEmpty()) continue; @@ -529,7 +525,7 @@ bool QmlProfilerData::save(const QString &filename) minimum = i; } } - if (minimum == QQmlProfilerDefinitions::MaximumRangeType) + if (minimum == MaximumRangeType) break; while (!pointEvents.isEmpty() && pointEvents.front().timestamp() < minimumTime) @@ -543,15 +539,15 @@ bool QmlProfilerData::save(const QString &filename) for (const QQmlProfilerEvent &event : qAsConst(d->events)) { const QQmlProfilerEventType &type = d->eventTypes.at(event.typeIndex()); - if (type.rangeType() != QQmlProfilerDefinitions::MaximumRangeType) { + if (type.rangeType() != MaximumRangeType) { QQueue<QQmlProfilerEvent> &starts = rangeStarts[type.rangeType()]; switch (event.rangeStage()) { - case QQmlProfilerDefinitions::RangeStart: { + case RangeStart: { ++level; starts.enqueue(event); break; } - case QQmlProfilerDefinitions::RangeEnd: { + case RangeEnd: { QStack<qint64> &ends = rangeEnds[type.rangeType()]; if (starts.length() > ends.length()) { ends.push(event.timestamp()); @@ -571,7 +567,7 @@ bool QmlProfilerData::save(const QString &filename) } } - for (int i = 0; i < QQmlProfilerDefinitions::MaximumRangeType; ++i) { + for (int i = 0; i < MaximumRangeType; ++i) { while (rangeEnds[i].length() < rangeStarts[i].length()) { rangeEnds[i].push(d->traceEndTime); --level; diff --git a/tools/qmlprofiler/qmlprofilerdata.h b/tools/qmlprofiler/qmlprofilerdata.h index 2be0b73aee..16ebc37f28 100644 --- a/tools/qmlprofiler/qmlprofilerdata.h +++ b/tools/qmlprofiler/qmlprofilerdata.h @@ -29,7 +29,7 @@ #ifndef QMLPROFILERDATA_H #define QMLPROFILERDATA_H -#include <private/qqmlprofilerdefinitions_p.h> +#include <private/qqmlprofilerclientdefinitions_p.h> #include <private/qqmlprofilereventlocation_p.h> #include <private/qqmlprofilereventreceiver_p.h> @@ -55,8 +55,8 @@ public: void addEvent(const QQmlProfilerEvent &event) override; static QString getHashStringForQmlEvent(const QQmlProfilerEventLocation &location, int eventType); - static QString qmlRangeTypeAsString(QQmlProfilerDefinitions::RangeType type); - static QString qmlMessageAsString(QQmlProfilerDefinitions::Message type); + static QString qmlRangeTypeAsString(RangeType type); + static QString qmlMessageAsString(Message type); qint64 traceStartTime() const; qint64 traceEndTime() const; diff --git a/tools/tools.pro b/tools/tools.pro index 2f32e681b6..8d6308b5c0 100644 --- a/tools/tools.pro +++ b/tools/tools.pro @@ -4,7 +4,7 @@ SUBDIRS += \ qmlmin \ qmlimportscanner -qtConfig(commandlineparser): SUBDIRS += qmlcachegen +qtConfig(commandlineparser):qtConfig(xmlstreamwriter): SUBDIRS += qmlcachegen !emscripten:!android|android_app { SUBDIRS += \ qml \ |