diff options
author | Liang Qi <liang.qi@qt.io> | 2017-02-28 13:04:16 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2017-02-28 13:04:17 +0100 |
commit | afec9016d0fd51345ea93a1bbadb99b5c3fdf629 (patch) | |
tree | 39aa0d02457c643065fbfb298645b2f3877c92bb | |
parent | bb1acc24587ebdecc4051ef4b573ef32cfb8a8c5 (diff) | |
parent | ba68c325688acf3072715757480497524f61c425 (diff) |
Merge remote-tracking branch 'origin/5.9' into dev
Change-Id: I92b13a9c1727644d63e125c1e6f1fdac72720ad7
51 files changed, 577 insertions, 107 deletions
diff --git a/examples/quick/canvas/smile/smile.qml b/examples/quick/canvas/smile/smile.qml index eebfee2d77..25e9d031de 100644 --- a/examples/quick/canvas/smile/smile.qml +++ b/examples/quick/canvas/smile/smile.qml @@ -101,14 +101,14 @@ Item { ctx.moveTo(75 + 50 * Math.cos(0), 75 - 50 * Math.sin(Math.PI*2)); ctx.arc(75,75,50,0,Math.PI*2,true); // Outer circle - ctx.moveTo(75,70); - ctx.arc(75,70,35,0,Math.PI,false); // Mouth (clockwise) - ctx.moveTo(60,65); - ctx.arc(60,65,5,0,Math.PI*2,true); // Left eye + ctx.moveTo(60,60); + ctx.arc(60,60,5,0,Math.PI*2,true); // Left eye ctx.moveTo(90 + 5 * Math.cos(0), 65 - 5 * Math.sin(Math.PI*2)); - ctx.moveTo(90,65); - ctx.arc(90,65,5,0,Math.PI*2,true); // Right eye + ctx.moveTo(90,60); + ctx.arc(90,60,5,-Math.PI,Math.PI*3,false); // Right eye + ctx.moveTo(75,70); + ctx.arc(75,70,35,0,Math.PI,false); // Mouth (clockwise) ctx.closePath(); if (canvas.fill) ctx.fill(); diff --git a/src/imports/layouts/qquicklayout.cpp b/src/imports/layouts/qquicklayout.cpp index 55ee3b63c6..df64b593d9 100644 --- a/src/imports/layouts/qquicklayout.cpp +++ b/src/imports/layouts/qquicklayout.cpp @@ -696,13 +696,20 @@ QQuickLayout::QQuickLayout(QQuickLayoutPrivate &dd, QQuickItem *parent) { } +static QQuickItemPrivate::ChangeTypes changeTypes = + QQuickItemPrivate::SiblingOrder + | QQuickItemPrivate::ImplicitWidth + | QQuickItemPrivate::ImplicitHeight + | QQuickItemPrivate::Destroyed + | QQuickItemPrivate::Visibility; + QQuickLayout::~QQuickLayout() { d_func()->m_isReady = false; const auto childItems = d_func()->childItems; for (QQuickItem *child : childItems) - QQuickItemPrivate::get(child)->removeItemChangeListener(this, QQuickItemPrivate::SiblingOrder); + QQuickItemPrivate::get(child)->removeItemChangeListener(this, changeTypes); } QQuickLayoutAttached *QQuickLayout::qmlAttachedProperties(QObject *object) @@ -766,14 +773,14 @@ void QQuickLayout::itemChange(ItemChange change, const ItemChangeData &value) Q_D(QQuickLayout); QQuickItem *item = value.item; qmlobject_connect(item, QQuickItem, SIGNAL(baselineOffsetChanged(qreal)), this, QQuickLayout, SLOT(invalidateSenderItem())); - QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::SiblingOrder | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight | QQuickItemPrivate::Destroyed | QQuickItemPrivate::Visibility); + QQuickItemPrivate::get(item)->addItemChangeListener(this, changeTypes); d->m_hasItemChangeListeners = true; if (isReady()) updateLayoutItems(); } else if (change == ItemChildRemovedChange) { QQuickItem *item = value.item; qmlobject_disconnect(item, QQuickItem, SIGNAL(baselineOffsetChanged(qreal)), this, QQuickLayout, SLOT(invalidateSenderItem())); - QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::SiblingOrder | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight | QQuickItemPrivate::Destroyed | QQuickItemPrivate::Visibility); + QQuickItemPrivate::get(item)->removeItemChangeListener(this, changeTypes); if (isReady()) updateLayoutItems(); } @@ -821,7 +828,7 @@ void QQuickLayout::deactivateRecur() // When deleting a layout with children, there is no reason for the children to inform the layout that their // e.g. visibility got changed. The layout already knows that all its children will eventually become invisible, so // we therefore remove its change listener. - QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::SiblingOrder | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight | QQuickItemPrivate::Destroyed | QQuickItemPrivate::Visibility); + QQuickItemPrivate::get(item)->removeItemChangeListener(this, changeTypes); if (QQuickLayout *layout = qobject_cast<QQuickLayout*>(item)) layout->deactivateRecur(); } diff --git a/src/particles/qquickcustomparticle_p.h b/src/particles/qquickcustomparticle_p.h index 1d48786a41..e2292cb33b 100644 --- a/src/particles/qquickcustomparticle_p.h +++ b/src/particles/qquickcustomparticle_p.h @@ -53,7 +53,6 @@ #include "qquickparticlepainter_p.h" #include <private/qquickopenglshadereffectnode_p.h> #include <private/qquickopenglshadereffect_p.h> -#include <QSignalMapper> QT_BEGIN_NAMESPACE diff --git a/src/particles/qquickparticlesystem.cpp b/src/particles/qquickparticlesystem.cpp index b60180b2ed..99e278238b 100644 --- a/src/particles/qquickparticlesystem.cpp +++ b/src/particles/qquickparticlesystem.cpp @@ -575,9 +575,6 @@ QQuickParticleSystem::QQuickParticleSystem(QQuickItem *parent) : m_paused(false), m_empty(true) { - connect(&m_painterMapper, SIGNAL(mapped(QObject*)), - this, SLOT(loadPainter(QObject*))); - m_debugMode = qmlParticlesDebug(); } @@ -615,8 +612,8 @@ void QQuickParticleSystem::registerParticlePainter(QQuickParticlePainter* p) qDebug() << "Registering Painter" << p << "to" << this; //TODO: a way to Unregister emitters, painters and affectors m_painters << QPointer<QQuickParticlePainter>(p);//###Set or uniqueness checking? - connect(p, SIGNAL(groupsChanged(QStringList)), - &m_painterMapper, SLOT(map())); + + connect(p, &QQuickParticlePainter::groupsChanged, this, [this, p] { this->loadPainter(p); }, Qt::QueuedConnection); loadPainter(p); } @@ -802,13 +799,11 @@ void QQuickParticleSystem::reset() } -void QQuickParticleSystem::loadPainter(QObject *p) +void QQuickParticleSystem::loadPainter(QQuickParticlePainter *painter) { - if (!m_componentComplete || !p) + if (!m_componentComplete || !painter) return; - QQuickParticlePainter* painter = qobject_cast<QQuickParticlePainter*>(p); - Q_ASSERT(painter);//XXX for (QQuickParticleGroupData* sg : groupData) { sg->painters.removeOne(painter); } diff --git a/src/particles/qquickparticlesystem_p.h b/src/particles/qquickparticlesystem_p.h index de39b436e2..92dca40419 100644 --- a/src/particles/qquickparticlesystem_p.h +++ b/src/particles/qquickparticlesystem_p.h @@ -56,7 +56,6 @@ #include <QVector> #include <QHash> #include <QPointer> -#include <QSignalMapper> #include <private/qquicksprite_p.h> #include <QAbstractAnimation> #include <QtQml/qqml.h> @@ -393,7 +392,7 @@ protected: private Q_SLOTS: void emittersChanged(); - void loadPainter(QObject* p); + void loadPainter(QQuickParticlePainter *p); void createEngine(); //Not invoked by sprite engine, unlike Sprite uses void particleStateChange(int idx); @@ -461,8 +460,6 @@ private: QSet<int> m_reusableIndexes; bool m_componentComplete; - QSignalMapper m_painterMapper; - QSignalMapper m_emitterMapper; bool m_paused; bool m_allDead; bool m_empty; diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index fae4e48066..0afc97e4bf 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -73,6 +73,25 @@ static inline void setLocation(IR::Stmt *s, const SourceLocation &loc) s->location = loc; } +static bool cjumpCanHandle(IR::AluOp op) +{ + switch (op) { + case IR::OpIn: + case IR::OpInstanceof: + case IR::OpEqual: + case IR::OpNotEqual: + case IR::OpGe: + case IR::OpGt: + case IR::OpLe: + case IR::OpLt: + case IR::OpStrictEqual: + case IR::OpStrictNotEqual: + return true; + default: + return false; + } +} + Codegen::ScanFunctions::ScanFunctions(Codegen *cg, const QString &sourceCode, CompilationMode defaultProgramMode) : _cg(cg) , _sourceCode(sourceCode) @@ -727,7 +746,7 @@ IR::Stmt *Codegen::cjump(IR::Expr *cond, IR::BasicBlock *iftrue, IR::BasicBlock if (hasError) return 0; - if (! (cond->asTemp() || cond->asBinop())) { + if (! (cond->asTemp() || (cond->asBinop() && cjumpCanHandle(cond->asBinop()->op)) )) { const unsigned t = _block->newTemp(); move(_block->TEMP(t), cond); cond = _block->TEMP(t); @@ -1293,14 +1312,7 @@ bool Codegen::visit(BinaryExpression *ast) if (_expr.accept(cx)) { setLocation(cjump(binop(IR::binaryOperator(ast->op), left, *right, ast->operatorToken), _expr.iftrue, _expr.iffalse), ast->operatorToken); } else { - IR::Expr *e = binop(IR::binaryOperator(ast->op), left, *right, ast->operatorToken); - if (e->asConst() || e->asString()) - _expr.code = e; - else { - const unsigned t = _block->newTemp(); - setLocation(move(_block->TEMP(t), e), ast->operatorToken); - _expr.code = _block->TEMP(t); - } + _expr.code = binop(IR::binaryOperator(ast->op), left, *right, ast->operatorToken); } break; } @@ -1326,14 +1338,7 @@ bool Codegen::visit(BinaryExpression *ast) if (hasError) return false; - IR::Expr *e = binop(IR::binaryOperator(ast->op), left, *right, ast->operatorToken); - if (e->asConst() || e->asString()) - _expr.code = e; - else { - const unsigned t = _block->newTemp(); - setLocation(move(_block->TEMP(t), e), ast->operatorToken); - _expr.code = _block->TEMP(t); - } + _expr.code = binop(IR::binaryOperator(ast->op), left, *right, ast->operatorToken); break; } diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index cd822a2614..9cfac4a676 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -220,7 +220,7 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorO registerString(*f->locals.at(i)); } - CompiledData::LEUInt32 *functionOffsets = reinterpret_cast<CompiledData::LEUInt32*>(alloca(irModule->functions.size() * sizeof(CompiledData::LEUInt32))); + Q_ALLOCA_VAR(CompiledData::LEUInt32, functionOffsets, irModule->functions.size() * sizeof(CompiledData::LEUInt32)); uint jsClassDataOffset = 0; char *dataPtr; diff --git a/src/qml/doc/src/cppintegration/definetypes.qdoc b/src/qml/doc/src/cppintegration/definetypes.qdoc index e06451b2bc..7d4a543089 100644 --- a/src/qml/doc/src/cppintegration/definetypes.qdoc +++ b/src/qml/doc/src/cppintegration/definetypes.qdoc @@ -282,6 +282,9 @@ int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor) template<typename T, int metaObjectRevision> int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason) + +template<typename T, typename E, int metaObjectRevision> +int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason) \endcode For example, if \c BaseType is changed and now has a revision 1, you can diff --git a/src/qml/doc/src/cppintegration/topic.qdoc b/src/qml/doc/src/cppintegration/topic.qdoc index a349fd0713..1aa3bb6ab5 100644 --- a/src/qml/doc/src/cppintegration/topic.qdoc +++ b/src/qml/doc/src/cppintegration/topic.qdoc @@ -30,7 +30,7 @@ \brief Description of how to integrate QML and C++ code QML is designed to be easily extensible through C++ code. The classes in the \l {Qt QML} module -enables QML objects to be loaded and manipulated from C++, and the nature of QML engine's +enable QML objects to be loaded and manipulated from C++, and the nature of QML engine's integration with Qt's \l{Meta Object System}{meta object system} enables C++ functionality to be invoked directly from QML. This allows the development of hybrid applications which are implemented with a mixture of QML, JavaScript and C++ code. diff --git a/src/qml/doc/src/javascript/imports.qdoc b/src/qml/doc/src/javascript/imports.qdoc index d4ce25c92b..489da08ada 100644 --- a/src/qml/doc/src/javascript/imports.qdoc +++ b/src/qml/doc/src/javascript/imports.qdoc @@ -56,10 +56,10 @@ import "jsfile.js" as Logic \endcode Imported JavaScript resources are always qualified using the "as" keyword. The -qualifier for JavaScript resources must be unique, so there is always a -one-to-one mapping between qualifiers and JavaScript files. (This also means -qualifiers cannot be named the same as built-in JavaScript objects such as -\c Date and \c Math). +qualifier for JavaScript resources must start with an uppercase letter, and must +be unique, so there is always a one-to-one mapping between qualifiers and JavaScript +files. (This also means qualifiers cannot be named the same as built-in JavaScript +objects such as \c Date and \c Math). The functions defined in an imported JavaScript file are available to objects defined in the importing QML document, via the diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc index 030eb72b5f..33f58dc1b9 100644 --- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc +++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc @@ -630,7 +630,7 @@ a \l {MouseArea::}{clicked} signal that is emitted when the user clicks within the mouse area. An object can be notified through a \l{Signal handler attributes} -{signal handler} whenever it a particular signal is emitted. A signal handler +{signal handler} whenever a particular signal is emitted. A signal handler is declared with the syntax \e on<Signal> where \e <Signal> is the name of the signal, with the first letter capitalized. The signal handler must be declared within the definition of the object that emits the signal, and the handler diff --git a/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc b/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc index ffbf2282a6..a486b47f03 100644 --- a/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc +++ b/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc @@ -324,6 +324,9 @@ property is only invoked when the property is reassigned to a different object v \li Values in the list are accessed using the \c [index] syntax \endlist + Values can be dynamically added to the list by using the \c push method, + as if it were a JavaScript Array + A \c list can only store QML objects, and cannot contain any \l {QML Basic Types}{basic type} values. (To store basic types within a list, use the \l var type instead.) diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp index 6d20a4e042..22067bbb13 100644 --- a/src/qml/jit/qv4binop.cpp +++ b/src/qml/jit/qv4binop.cpp @@ -331,7 +331,6 @@ void Binop<JITAssembler>::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *ta break; default: { - Q_ASSERT(target->type == IR::BoolType); Jump trueCase = as->branchDouble(false, op, lhs, rhs); as->storeBool(false, target); Jump done = as->jump(); diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index d5da863ee0..e5abaa7458 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -1575,7 +1575,7 @@ static void longestAvailableReg(int *nextUses, int nextUseCount, int ®, int & #define CALLOC_ON_STACK(ty, ptr, sz, val) \ Q_ASSERT(sz > 0); \ - ty *ptr = reinterpret_cast<ty *>(alloca(sizeof(ty) * (sz))); \ + Q_ALLOCA_VAR(ty, ptr, sizeof(ty) * (sz)); \ for (ty *it = ptr, *eit = ptr + (sz); it != eit; ++it) \ *it = val; diff --git a/src/qml/jit/qv4targetplatform_p.h b/src/qml/jit/qv4targetplatform_p.h index 725567fa05..fcc600eb2e 100644 --- a/src/qml/jit/qv4targetplatform_p.h +++ b/src/qml/jit/qv4targetplatform_p.h @@ -207,6 +207,7 @@ public: << RI(JSC::X86Registers::edx, QStringLiteral("rdx"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc) << RI(JSC::X86Registers::r9, QStringLiteral("r9"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc) << RI(JSC::X86Registers::r8, QStringLiteral("r8"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc) + // r11 is used as scratch register by the macro assembler << RI(JSC::X86Registers::r12, QStringLiteral("r12"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) << RI(JSC::X86Registers::r13, QStringLiteral("r13"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc) << RI(JSC::X86Registers::r14, QStringLiteral("r14"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) @@ -265,10 +266,7 @@ public: using FPRegisterID = PlatformAssembler::FPRegisterID; using TrustedImm32 = PlatformAssembler::TrustedImm32; - // Register allocation is not (yet) supported on win64, because the ABI related stack handling - // is not completely implemented. Specifically, the saving of xmm registers, and the saving of - // incoming function parameters to the shadow space is missing. - enum { RegAllocIsSupported = 0 }; + enum { RegAllocIsSupported = 1 }; static const RegisterID FramePointerRegister = JSC::X86Registers::ebp; static const RegisterID StackPointerRegister = JSC::X86Registers::esp; @@ -283,16 +281,23 @@ public: { typedef RegisterInfo RI; static RegisterInformation info = RegisterInformation() - << RI(JSC::X86Registers::ebx, QStringLiteral("rbx"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) - << RI(JSC::X86Registers::edi, QStringLiteral("rdi"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) - << RI(JSC::X86Registers::esi, QStringLiteral("rsi"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) - << RI(JSC::X86Registers::edx, QStringLiteral("rdx"), RI::RegularRegister, RI::CallerSaved, RI::Predefined) - << RI(JSC::X86Registers::r9, QStringLiteral("r9"), RI::RegularRegister, RI::CallerSaved, RI::Predefined) - << RI(JSC::X86Registers::r8, QStringLiteral("r8"), RI::RegularRegister, RI::CallerSaved, RI::Predefined) + << RI(JSC::X86Registers::ebx, QStringLiteral("rbx"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc) + << RI(JSC::X86Registers::edi, QStringLiteral("rdi"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc) + << RI(JSC::X86Registers::esi, QStringLiteral("rsi"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc) + << RI(JSC::X86Registers::edx, QStringLiteral("rdx"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc) + << RI(JSC::X86Registers::r8, QStringLiteral("r8"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc) + << RI(JSC::X86Registers::r9, QStringLiteral("r9"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc) + // r11 is used as scratch register by the macro assembler << RI(JSC::X86Registers::r12, QStringLiteral("r12"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) - << RI(JSC::X86Registers::r13, QStringLiteral("r13"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) + << RI(JSC::X86Registers::r13, QStringLiteral("r13"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc) << RI(JSC::X86Registers::r14, QStringLiteral("r14"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) - << RI(JSC::X86Registers::r15, QStringLiteral("r15"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) + << RI(JSC::X86Registers::r15, QStringLiteral("r15"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc) + << RI(JSC::X86Registers::xmm2, QStringLiteral("xmm2"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc) + << RI(JSC::X86Registers::xmm3, QStringLiteral("xmm3"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc) + << RI(JSC::X86Registers::xmm4, QStringLiteral("xmm4"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc) + << RI(JSC::X86Registers::xmm5, QStringLiteral("xmm5"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc) + << RI(JSC::X86Registers::xmm6, QStringLiteral("xmm6"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc) + << RI(JSC::X86Registers::xmm7, QStringLiteral("xmm7"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc) ; return info; } @@ -311,7 +316,7 @@ public: }; Q_ASSERT(index >= 0 && index < RegisterArgumentCount); return regs[index]; - }; + } static const int StackAlignment = 16; static const int StackShadowSpace = 32; diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index e31b28d303..39b433e5f9 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -258,6 +258,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) arrayClass = emptyClass->addMember(id_length(), Attr_NotConfigurable|Attr_NotEnumerable); jsObjects[ArrayProto] = memoryManager->allocObject<ArrayPrototype>(arrayClass, objectPrototype()); + jsObjects[PropertyListProto] = memoryManager->allocObject<PropertyListPrototype>(); InternalClass *argsClass = emptyClass->addMember(id_length(), Attr_NotEnumerable); argumentsObjectClass = argsClass->addMember(id_callee(), Attr_Data|Attr_NotEnumerable); @@ -360,6 +361,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) static_cast<NumberPrototype *>(numberPrototype())->init(this, numberCtor()); static_cast<BooleanPrototype *>(booleanPrototype())->init(this, booleanCtor()); static_cast<ArrayPrototype *>(arrayPrototype())->init(this, arrayCtor()); + static_cast<PropertyListPrototype *>(propertyListPrototype())->init(this); static_cast<DatePrototype *>(datePrototype())->init(this, dateCtor()); static_cast<FunctionPrototype *>(functionPrototype())->init(this, functionCtor()); static_cast<RegExpPrototype *>(regExpPrototype())->init(this, regExpCtor()); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 1c20ad30aa..69aa389c44 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -157,6 +157,7 @@ public: IntegerNull, // Has to come after the RootContext to make the context stack safe ObjectProto, ArrayProto, + PropertyListProto, StringProto, NumberProto, BooleanProto, @@ -225,6 +226,7 @@ public: Object *objectPrototype() const { return reinterpret_cast<Object *>(jsObjects + ObjectProto); } Object *arrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayProto); } + Object *propertyListPrototype() const { return reinterpret_cast<Object *>(jsObjects + PropertyListProto); } Object *stringPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringProto); } Object *numberPrototype() const { return reinterpret_cast<Object *>(jsObjects + NumberProto); } Object *booleanPrototype() const { return reinterpret_cast<Object *>(jsObjects + BooleanProto); } diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 283c3dad04..c9b4b433bd 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -676,18 +676,24 @@ void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name QObjectWrapper *that = static_cast<QObjectWrapper*>(m); - if (that->d()->object()) { - const QMetaObject *mo = that->d()->object()->metaObject(); + QObject *thatObject = that->d()->object(); + if (thatObject && !QQmlData::wasDeleted(thatObject)) { + const QMetaObject *mo = thatObject->metaObject(); // These indices don't apply to gadgets, so don't block them. const bool preventDestruction = mo->superClass() || mo == &QObject::staticMetaObject; const int propertyCount = mo->propertyCount(); if (it->arrayIndex < static_cast<uint>(propertyCount)) { - Scope scope(that->engine()); - ScopedString propName(scope, that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name()))); + ExecutionEngine *thatEngine = that->engine(); + Scope scope(thatEngine); + const QMetaProperty property = mo->property(it->arrayIndex); + ScopedString propName(scope, thatEngine->newString(QString::fromUtf8(property.name()))); name->setM(propName->d()); ++it->arrayIndex; *attributes = QV4::Attr_Data; - p->value = that->get(propName); + + QQmlPropertyData local; + local.load(property); + p->value = that->getProperty(thatEngine, thatObject, &local); return; } const int methodCount = mo->methodCount(); @@ -697,11 +703,15 @@ void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name ++it->arrayIndex; if (method.access() == QMetaMethod::Private || (preventDestruction && (index == deleteLaterIdx || index == destroyedIdx1 || index == destroyedIdx2))) continue; - Scope scope(that->engine()); - ScopedString methodName(scope, that->engine()->newString(QString::fromUtf8(method.name()))); + ExecutionEngine *thatEngine = that->engine(); + Scope scope(thatEngine); + ScopedString methodName(scope, thatEngine->newString(QString::fromUtf8(method.name()))); name->setM(methodName->d()); *attributes = QV4::Attr_Data; - p->value = that->get(methodName); + + QQmlPropertyData local; + local.load(method); + p->value = that->getProperty(thatEngine, thatObject, &local); return; } } diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 40682aaa4b..0894d0c25b 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -367,7 +367,7 @@ void RegExpPrototype::method_exec(const BuiltinFunction *, Scope &scope, CallDat RETURN_RESULT(Encode::null()); } - uint* matchOffsets = (uint*)alloca(r->value()->captureCount() * 2 * sizeof(uint)); + Q_ALLOCA_VAR(uint, matchOffsets, r->value()->captureCount() * 2 * sizeof(uint)); const int result = Scoped<RegExp>(scope, r->value())->match(s, offset, matchOffsets); Scoped<RegExpCtor> regExpCtor(scope, scope.engine->regExpCtor()); diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index d17ac6ddc8..72be11eca0 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -650,7 +650,7 @@ void StringPrototype::method_search(const BuiltinFunction *, Scope &scope, CallD Q_ASSERT(regExp); } Scoped<RegExp> re(scope, regExp->value()); - uint* matchOffsets = (uint*)alloca(regExp->value()->captureCount() * 2 * sizeof(uint)); + Q_ALLOCA_VAR(uint, matchOffsets, regExp->value()->captureCount() * 2 * sizeof(uint)); uint result = re->match(string, /*offset*/0, matchOffsets); if (result == JSC::Yarr::offsetNoMatch) scope.result = Encode(-1); @@ -721,7 +721,7 @@ void StringPrototype::method_split(const BuiltinFunction *, Scope &scope, CallDa ScopedString s(scope); if (re) { uint offset = 0; - uint* matchOffsets = (uint*)alloca(re->value()->captureCount() * 2 * sizeof(uint)); + Q_ALLOCA_VAR(uint, matchOffsets, re->value()->captureCount() * 2 * sizeof(uint)); while (true) { Scoped<RegExp> regexp(scope, re->value()); uint result = regexp->match(text, offset, matchOffsets); diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index b9183313cd..be2772c23f 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -402,7 +402,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code } } - QV4::Value **scopes = static_cast<QV4::Value **>(alloca(sizeof(QV4::Value *)*(2 + 2*scopeDepth))); + Q_ALLOCA_VAR(QV4::Value*, scopes, sizeof(QV4::Value *)*(2 + 2*scopeDepth)); { scopes[0] = const_cast<QV4::Value *>(context->d()->compilationUnit->constants); // stack gets setup in push instruction @@ -957,8 +957,6 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code return QV4::Encode::undefined(); code = exceptionHandler; } - - } #ifdef MOTH_THREADED_INTERPRETER diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 1609dd5adb..a829e902fb 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -385,7 +385,7 @@ void Chunk::sortIntoBins(HeapItem **bins, uint nBins) } } #ifndef QT_NO_DEBUG - Q_ASSERT(freeSlots + allocatedSlots == EntriesInBitmap*8*sizeof(quintptr)); + Q_ASSERT(freeSlots + allocatedSlots == (EntriesInBitmap - start) * 8 * sizeof(quintptr)); #endif } @@ -643,7 +643,7 @@ MemoryManager::MemoryManager(ExecutionEngine *engine) } #ifndef QT_NO_DEBUG -static int lastAllocRequestedSlots = 0; +static size_t lastAllocRequestedSlots = 0; #endif Heap::Base *MemoryManager::allocString(std::size_t unmanagedSize) diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index f0973338ea..ddb4af0b81 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -238,6 +238,44 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); } +template<typename T, typename E, int metaObjectRevision> +int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason) +{ + QML_GETTYPENAMES + + QQmlAttachedPropertiesFunc attached = QQmlPrivate::attachedPropertiesFunc<E>(); + const QMetaObject * attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<E>(); + if (!attached) { + attached = QQmlPrivate::attachedPropertiesFunc<T>(); + attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<T>(); + } + + QQmlPrivate::RegisterType type = { + 1, + + qRegisterNormalizedMetaType<T *>(pointerName.constData()), + qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), + 0, + Q_NULLPTR, + reason, + + uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + + attached, + attachedMetaObject, + + QQmlPrivate::StaticCastSelector<T,QQmlParserStatus>::cast(), + QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(), + QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(), + + QQmlPrivate::createParent<E>, &E::staticMetaObject, + + Q_NULLPTR, + metaObjectRevision + }; + + return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); +} Q_QML_EXPORT int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject, const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason); diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp index 2a96d96302..a10dda166c 100644 --- a/src/qml/qml/qqmlapplicationengine.cpp +++ b/src/qml/qml/qqmlapplicationengine.cpp @@ -66,8 +66,6 @@ void QQmlApplicationEnginePrivate::cleanUp() void QQmlApplicationEnginePrivate::init() { Q_Q(QQmlApplicationEngine); - q->connect(&statusMapper, SIGNAL(mapped(QObject*)), - q, SLOT(_q_finishLoad(QObject*))); q->connect(q, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit())); q->connect(q, &QQmlApplicationEngine::exit, QCoreApplication::instance(), &QCoreApplication::exit); #if QT_CONFIG(translation) @@ -113,20 +111,15 @@ void QQmlApplicationEnginePrivate::startLoad(const QUrl &url, const QByteArray & c->loadUrl(url); if (!c->isLoading()) { - _q_finishLoad(c); + finishLoad(c); return; } - statusMapper.setMapping(c, c); - q->connect(c, SIGNAL(statusChanged(QQmlComponent::Status)), - &statusMapper, SLOT(map())); + QObject::connect(c, &QQmlComponent::statusChanged, q, [this, c] { this->finishLoad(c); }); } -void QQmlApplicationEnginePrivate::_q_finishLoad(QObject *o) +void QQmlApplicationEnginePrivate::finishLoad(QQmlComponent *c) { Q_Q(QQmlApplicationEngine); - QQmlComponent *c = qobject_cast<QQmlComponent *>(o); - if (!c) - return; switch (c->status()) { case QQmlComponent::Error: qWarning() << "QQmlApplicationEngine failed to load component"; diff --git a/src/qml/qml/qqmlapplicationengine.h b/src/qml/qml/qqmlapplicationengine.h index e64d7495cd..6c57f46c72 100644 --- a/src/qml/qml/qqmlapplicationengine.h +++ b/src/qml/qml/qqmlapplicationengine.h @@ -74,7 +74,6 @@ Q_SIGNALS: private: Q_DISABLE_COPY(QQmlApplicationEngine) Q_DECLARE_PRIVATE(QQmlApplicationEngine) - Q_PRIVATE_SLOT(d_func(), void _q_finishLoad(QObject*)) }; QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlapplicationengine_p.h b/src/qml/qml/qqmlapplicationengine_p.h index 8c342a43a9..4795170bed 100644 --- a/src/qml/qml/qqmlapplicationengine_p.h +++ b/src/qml/qml/qqmlapplicationengine_p.h @@ -42,7 +42,6 @@ #include "qqmlapplicationengine.h" #include "qqmlengine_p.h" -#include <QSignalMapper> #include <QCoreApplication> #include <QFileInfo> #include <QLibraryInfo> @@ -73,9 +72,8 @@ public: void startLoad(const QUrl &url, const QByteArray &data = QByteArray(), bool dataFlag = false); void loadTranslations(const QUrl &rootFile); - void _q_finishLoad(QObject *component); + void finishLoad(QQmlComponent *component); QList<QObject *> objects; - QSignalMapper statusMapper; QObject *appObj; #if QT_CONFIG(translation) diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp index e2da1b7ff4..43677e0d78 100644 --- a/src/qml/qml/qqmllistwrapper.cpp +++ b/src/qml/qml/qqmllistwrapper.cpp @@ -166,4 +166,29 @@ void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name return QV4::Object::advanceIterator(m, it, name, index, p, attrs); } +void PropertyListPrototype::init(ExecutionEngine *) +{ + defineDefaultProperty(QStringLiteral("push"), method_push, 1); +} + +void PropertyListPrototype::method_push(const BuiltinFunction *, Scope &scope, CallData *callData) +{ + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); + if (!instance) + RETURN_UNDEFINED(); + QmlListWrapper *w = instance->as<QmlListWrapper>(); + if (!w) + RETURN_UNDEFINED(); + if (!w->d()->property().append) + THROW_GENERIC_ERROR("List doesn't define an Append function"); + + QV4::ScopedObject so(scope); + for (int i = 0; i < callData->argc; ++i) + { + so = callData->args[i].toObject(scope.engine); + if (QV4::QObjectWrapper *wrapper = so->as<QV4::QObjectWrapper>()) + w->d()->property().append(&w->d()->property(), wrapper->object() ); + } +} + QT_END_NAMESPACE diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h index 3a49b4b8ce..84dadba01a 100644 --- a/src/qml/qml/qqmllistwrapper_p.h +++ b/src/qml/qml/qqmllistwrapper_p.h @@ -86,6 +86,7 @@ struct Q_QML_EXPORT QmlListWrapper : Object { V4_OBJECT2(QmlListWrapper, Object) V4_NEEDS_DESTROY + V4_PROTOTYPE(propertyListPrototype) static ReturnedValue create(ExecutionEngine *engine, QObject *object, int propId, int propType); static ReturnedValue create(ExecutionEngine *engine, const QQmlListProperty<QObject> &prop, int propType); @@ -98,6 +99,13 @@ struct Q_QML_EXPORT QmlListWrapper : Object static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes); }; +struct PropertyListPrototype : Object +{ + void init(ExecutionEngine *engine); + + static void method_push(const BuiltinFunction *, Scope &, CallData *callData); +}; + } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 8dda682ce8..d262b230e2 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -290,9 +290,11 @@ int QQmlValueTypeWrapper::typeId() const bool QQmlValueTypeWrapper::write(QObject *target, int propertyIndex) const { bool destructGadgetOnExit = false; + Q_ALLOCA_DECLARE(void, gadget); if (const QQmlValueTypeReference *ref = as<const QQmlValueTypeReference>()) { if (!d()->gadgetPtr) { - d()->gadgetPtr = alloca(d()->valueType->metaType.sizeOf()); + Q_ALLOCA_ASSIGN(void, gadget, d()->valueType->metaType.sizeOf()); + d()->gadgetPtr = gadget; d()->valueType->metaType.construct(d()->gadgetPtr, 0); destructGadgetOnExit = true; } diff --git a/src/qml/qtqmlglobal_p.h b/src/qml/qtqmlglobal_p.h index 63585fd62e..026be5a703 100644 --- a/src/qml/qtqmlglobal_p.h +++ b/src/qml/qtqmlglobal_p.h @@ -55,6 +55,46 @@ #include <QtQml/private/qtqml-config_p.h> #include <QtQml/qtqmlglobal.h> +// Define Q_ALLOCA_VAR macro to be used instead of #ifdeffing +// the occurrences of alloca() in case it's not supported. +// Q_ALLOCA_DECLARE and Q_ALLOCA_ASSIGN macros separate +// memory allocation from the declaration and RAII. +#define Q_ALLOCA_VAR(type, name, size) \ + Q_ALLOCA_DECLARE(type, name); \ + Q_ALLOCA_ASSIGN(type, name, size) + +#if QT_CONFIG(alloca) + +#define Q_ALLOCA_DECLARE(type, name) \ + type *name = 0 + +#define Q_ALLOCA_ASSIGN(type, name, size) \ + name = static_cast<type*>(alloca(size)) + +#else +QT_BEGIN_NAMESPACE +class Qt_AllocaWrapper +{ +public: + Qt_AllocaWrapper() { m_data = 0; } + ~Qt_AllocaWrapper() { free(m_data); } + void *data() { return m_data; } + void allocate(int size) { m_data = malloc(size); } +private: + void *m_data; +}; +QT_END_NAMESPACE + +#define Q_ALLOCA_DECLARE(type, name) \ + Qt_AllocaWrapper _qt_alloca_##name; \ + type *name = 0 + +#define Q_ALLOCA_ASSIGN(type, name, size) \ + _qt_alloca_##name.allocate(size); \ + name = static_cast<type*>(_qt_alloca_##name.data()) + +#endif + #if defined(QT_BUILD_QMLDEVTOOLS_LIB) || defined(QT_QMLDEVTOOLS_LIB) # define Q_QML_PRIVATE_EXPORT #else diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index 8f0dd32d7b..efc2828dc5 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -1268,7 +1268,7 @@ void ModelNodeMetaObject::updateValues() const int roleCount = m_model->m_listModel->roleCount(); if (!m_initialized) { if (roleCount) { - int *changedRoles = reinterpret_cast<int *>(alloca(roleCount * sizeof(int))); + Q_ALLOCA_VAR(int, changedRoles, roleCount * sizeof(int)); for (int i = 0; i < roleCount; ++i) changedRoles[i] = i; emitDirectNotifies(changedRoles, roleCount); diff --git a/src/qmldevtools/qtqmldevtoolsglobal_p.h b/src/qmldevtools/qtqmldevtoolsglobal_p.h index e1a01aa78d..5cb8a9275a 100644 --- a/src/qmldevtools/qtqmldevtoolsglobal_p.h +++ b/src/qmldevtools/qtqmldevtoolsglobal_p.h @@ -53,6 +53,10 @@ #include <QtCore/qglobal.h> +// All host systems are assumed to have alloca(). +#define Q_ALLOCA_VAR(type, name, size) \ + type *name = static_cast<type*>(alloca(size)) + QT_BEGIN_NAMESPACE #define Q_QML_EXPORT diff --git a/src/qmltest/quicktestevent.cpp b/src/qmltest/quicktestevent.cpp index 4b1adf5a90..dc7b917bc4 100644 --- a/src/qmltest/quicktestevent.cpp +++ b/src/qmltest/quicktestevent.cpp @@ -129,7 +129,7 @@ namespace QtQuickTest static void mouseEvent(MouseAction action, QWindow *window, QObject *item, Qt::MouseButton button, - Qt::KeyboardModifiers stateKey, QPointF _pos, int delay=-1) + Qt::KeyboardModifiers stateKey, const QPointF &_pos, int delay=-1) { QTEST_ASSERT(window); QTEST_ASSERT(item); diff --git a/src/quick/items/qquickopenglshadereffect_p.h b/src/quick/items/qquickopenglshadereffect_p.h index 64e79a9343..bc2e2975ee 100644 --- a/src/quick/items/qquickopenglshadereffect_p.h +++ b/src/quick/items/qquickopenglshadereffect_p.h @@ -70,7 +70,6 @@ QT_REQUIRE_CONFIG(quick_shadereffect); QT_BEGIN_NAMESPACE class QSGContext; -class QSignalMapper; class QFileSelector; class QQuickOpenGLCustomMaterialShader; diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 0ebd644d69..57810e4ec9 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1803,7 +1803,7 @@ bool QQuickWindowPrivate::deliverWheelEvent(QQuickItem *item, QWheelEvent *event QPointF p = item->mapFromScene(event->posF()); if (item->contains(p)) { - QWheelEvent wheel(p, p, event->pixelDelta(), event->angleDelta(), event->delta(), + QWheelEvent wheel(p, event->globalPosF(), event->pixelDelta(), event->angleDelta(), event->delta(), event->orientation(), event->buttons(), event->modifiers(), event->phase(), event->source(), event->inverted()); wheel.setTimestamp(event->timestamp()); wheel.accept(); diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp index d9ddcd71a7..63c2918325 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.cpp +++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp @@ -515,6 +515,8 @@ void registerTypes() qmlRegisterType<QObjectContainer>("Qt.test", 1, 0, "QObjectContainer"); qmlRegisterType<QObjectContainerWithGCOnAppend>("Qt.test", 1, 0, "QObjectContainerWithGCOnAppend"); qmlRegisterType<FloatingQObject>("Qt.test", 1, 0, "FloatingQObject"); + + qmlRegisterType<ClashingNames>("Qt.test", 1, 0, "ClashingNames"); } #include "testtypes.moc" diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h index 1f7f3344ef..eedeb66647 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.h +++ b/tests/auto/qml/qqmlecmascript/testtypes.h @@ -1714,6 +1714,14 @@ public: virtual void componentComplete(); }; +class ClashingNames : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool clashes READ clashes CONSTANT) +public: + Q_INVOKABLE bool clashes() const { return true; } +}; + void registerTypes(); #endif // TESTTYPES_H diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 44582817d5..91ceed7697 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -47,6 +47,7 @@ #include <private/qv4runtime_p.h> #include <private/qv4object_p.h> #include <private/qqmlcomponentattached_p.h> +#include <private/qv4objectiterator_p.h> #ifdef Q_CC_MSVC #define NO_INLINE __declspec(noinline) @@ -261,6 +262,7 @@ private slots: void nonNotifyable(); void deleteWhileBindingRunning(); void callQtInvokables(); + void resolveClashingProperties(); void invokableObjectArg(); void invokableObjectRet(); void invokableEnumRet(); @@ -2991,6 +2993,48 @@ void tst_qqmlecmascript::callQtInvokables() QVERIFY(callback.isCallable()); } +void tst_qqmlecmascript::resolveClashingProperties() +{ + ClashingNames *o = new ClashingNames(); + QQmlEngine qmlengine; + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(&qmlengine); + + QV4::ExecutionEngine *engine = QV8Engine::getV4(ep->v8engine()); + QV4::Scope scope(engine); + + QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(engine, o)); + QV4::ObjectIterator it(scope, object->as<QV4::Object>(), QV4::ObjectIterator::EnumerableOnly); + QV4::ScopedValue name(scope); + QV4::ScopedValue value(scope); + + bool seenProperty = false; + bool seenMethod = false; + while (true) { + QV4::Value v; + name = it.nextPropertyNameAsString(&v); + if (name->isNull()) + break; + QString key = name->toQStringNoThrow(); + if (key == QLatin1String("clashes")) { + value = v; + QV4::ScopedValue typeString(scope, QV4::Runtime::method_typeofValue(engine, value)); + QString type = typeString->toQStringNoThrow(); + if (type == QLatin1String("boolean")) { + QVERIFY(!seenProperty); + seenProperty = true; + } else if (type == QLatin1String("function")) { + QVERIFY(!seenMethod); + seenMethod = true; + } else { + QFAIL(qPrintable(QString::fromLatin1("found 'clashes' property of type %1") + .arg(type))); + } + } + } + QVERIFY(seenProperty); + QVERIFY(seenMethod); +} + // QTBUG-13047 (check that you can pass registered object types as args) void tst_qqmlecmascript::invokableObjectArg() { diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp index bc8c192a61..bdcdaa8137 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.cpp +++ b/tests/auto/qml/qqmllanguage/testtypes.cpp @@ -87,6 +87,10 @@ void registerTypes() qmlRegisterUncreatableType<MyUncreateableBaseClass,1>("Test", 1, 1, "MyUncreateableBaseClass", "Cannot create MyUncreateableBaseClass"); qmlRegisterType<MyCreateableDerivedClass,1>("Test", 1, 1, "MyCreateableDerivedClass"); + qmlRegisterExtendedUncreatableType<MyExtendedUncreateableBaseClass, MyExtendedUncreateableBaseClassExtension>("Test", 1, 0, "MyExtendedUncreateableBaseClass", "Cannot create MyExtendedUncreateableBaseClass"); + qmlRegisterExtendedUncreatableType<MyExtendedUncreateableBaseClass, MyExtendedUncreateableBaseClassExtension, 1>("Test", 1, 1, "MyExtendedUncreateableBaseClass", "Cannot create MyExtendedUncreateableBaseClass"); + qmlRegisterType<MyExtendedCreateableDerivedClass>("Test", 1, 0, "MyExtendedCreateableDerivedClass"); + qmlRegisterCustomType<CustomBinding>("Test", 1, 0, "CustomBinding", new CustomBindingParser); qmlRegisterCustomType<SimpleObjectWithCustomParser>("Test", 1, 0, "SimpleObjectWithCustomParser", new SimpleObjectCustomParser); diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index 6c62bcf7b9..7d7a8ac6d3 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -1021,6 +1021,60 @@ public: } }; +class MyExtendedUncreateableBaseClass : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool prop1 READ prop1 WRITE setprop1) + Q_PROPERTY(bool prop2 READ prop2 WRITE setprop2 REVISION 1) + Q_PROPERTY(bool prop3 READ prop3 WRITE setprop3 REVISION 1) +public: + explicit MyExtendedUncreateableBaseClass(QObject *parent = 0) + : QObject(parent), _prop1(false), _prop2(false), _prop3(false) + { + } + + bool _prop1; + bool prop1() const { return _prop1; } + void setprop1(bool p) { _prop1 = p; } + bool _prop2; + bool prop2() const { return _prop2; } + void setprop2(bool p) { _prop2 = p; } + bool _prop3; + bool prop3() const { return _prop3; } + void setprop3(bool p) { _prop3 = p; } +}; + +class MyExtendedUncreateableBaseClassExtension : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool prop4 READ prop4 WRITE setprop4) +public: + explicit MyExtendedUncreateableBaseClassExtension(QObject *parent = 0) + : QObject(parent), _prop4(false) + { + } + + bool _prop4; + bool prop4() const { return _prop4; } + void setprop4(bool p) { _prop4 = p; } +}; + +class MyExtendedCreateableDerivedClass : public MyExtendedUncreateableBaseClass +{ + Q_OBJECT + Q_PROPERTY(bool prop5 READ prop5 WRITE setprop5) + +public: + MyExtendedCreateableDerivedClass(QObject *parent = 0) + : MyExtendedUncreateableBaseClass(parent), _prop5(false) + { + } + + bool _prop5; + bool prop5() const { return _prop5; } + void setprop5(bool p) { _prop5 = p; } +}; + class MyVersion2Class : public QObject { Q_OBJECT diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index c0500afddd..750c32cc3c 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -189,6 +189,9 @@ private slots: void subclassedUncreateableRevision_data(); void subclassedUncreateableRevision(); + void subclassedExtendedUncreateableRevision_data(); + void subclassedExtendedUncreateableRevision(); + void uncreatableTypesAsProperties(); void propertyInit(); @@ -3228,6 +3231,62 @@ void tst_qqmllanguage::subclassedUncreateableRevision() delete obj; } +void tst_qqmllanguage::subclassedExtendedUncreateableRevision_data() +{ + QTest::addColumn<QString>("version"); + QTest::addColumn<QString>("prop"); + QTest::addColumn<bool>("shouldWork"); + + QTest::newRow("prop1 exists in 1.0") << "1.0" << "prop1" << true; + QTest::newRow("prop2 does not exist in 1.0") << "1.0" << "prop2" << false; + QTest::newRow("prop3 does not exist in 1.0") << "1.0" << "prop3" << false; + QTest::newRow("prop4 exists in 1.0") << "1.0" << "prop4" << true; + QTest::newRow("prop5 exists in 1.0") << "1.0" << "prop5" << true; + + QTest::newRow("prop1 exists in 1.1") << "1.1" << "prop1" << true; + QTest::newRow("prop2 exists in 1.1") << "1.1" << "prop2" << true; + QTest::newRow("prop3 exists in 1.1") << "1.1" << "prop3" << true; + QTest::newRow("prop4 exists in 1.1") << "1.1" << "prop4" << true; + QTest::newRow("prop5 exists in 1.1") << "1.1" << "prop5" << true; +} + +void tst_qqmllanguage::subclassedExtendedUncreateableRevision() +{ + QFETCH(QString, version); + QFETCH(QString, prop); + QFETCH(bool, shouldWork); + + { + QQmlEngine engine; + QString qml = QString("import QtQuick 2.0\nimport Test %1\nMyExtendedUncreateableBaseClass {}").arg(version); + QQmlComponent c(&engine); + QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready"); + c.setData(qml.toUtf8(), QUrl::fromLocalFile(QDir::currentPath())); + QObject *obj = c.create(); + QCOMPARE(obj, static_cast<QObject*>(0)); + QCOMPARE(c.errors().count(), 1); + QCOMPARE(c.errors().first().description(), QString("Cannot create MyExtendedUncreateableBaseClass")); + } + + QQmlEngine engine; + QString qml = QString("import QtQuick 2.0\nimport Test %1\nMyExtendedCreateableDerivedClass {\n%3: true\n}").arg(version).arg(prop); + QQmlComponent c(&engine); + if (!shouldWork) + QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready"); + c.setData(qml.toUtf8(), QUrl::fromLocalFile(QDir::currentPath())); + QObject *obj = c.create(); + if (!shouldWork) { + QCOMPARE(obj, static_cast<QObject*>(0)); + return; + } + + QVERIFY(obj); + MyExtendedUncreateableBaseClass *base = qobject_cast<MyExtendedUncreateableBaseClass*>(obj); + QVERIFY(base); + QCOMPARE(base->property(prop.toLatin1()).toBool(), true); + delete obj; +} + void tst_qqmllanguage::uncreatableTypesAsProperties() { QQmlEngine engine; diff --git a/tests/auto/qml/qqmllistreference/data/propertyList.qml b/tests/auto/qml/qqmllistreference/data/propertyList.qml new file mode 100644 index 0000000000..c791c6dcf0 --- /dev/null +++ b/tests/auto/qml/qqmllistreference/data/propertyList.qml @@ -0,0 +1,12 @@ +import QtQuick 2.7 + +Item { + id:root + + Component.onCompleted : { + var st1 = Qt.createQmlObject( "import QtQuick 2.7; State{ name: 'MyState1' }", root, "dynamicState1" ); + var st2 = Qt.createQmlObject( "import QtQuick 2.7; State{ name: 'MyState2' }", root, "dynamicState2" ); + root.states.push( st1, st2 ); + root.state = "MyState2"; + } +} diff --git a/tests/auto/qml/qqmllistreference/qqmllistreference.pro b/tests/auto/qml/qqmllistreference/qqmllistreference.pro index dceb7d1133..110d0d9c81 100644 --- a/tests/auto/qml/qqmllistreference/qqmllistreference.pro +++ b/tests/auto/qml/qqmllistreference/qqmllistreference.pro @@ -8,4 +8,4 @@ include (../../shared/util.pri) TESTDATA = data/* -QT += core-private gui-private qml-private testlib +QT += core-private gui-private quick-private qml-private testlib diff --git a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp index 4d33359eaa..5c16a48378 100644 --- a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp +++ b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp @@ -36,6 +36,7 @@ #include <QtQml/qqmlprivate.h> #include <QtQml/qqmlproperty.h> #include <QDebug> +#include <private/qquickstate_p.h> #include "../../shared/util.h" class tst_qqmllistreference : public QQmlDataTest @@ -65,6 +66,7 @@ private slots: void qmlmetaproperty(); void engineTypes(); void variantToList(); + void listProperty(); }; class TestType : public QObject @@ -618,6 +620,28 @@ void tst_qqmllistreference::variantToList() delete o; } +void tst_qqmllistreference::listProperty() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("propertyList.qml")); + + QScopedPointer<QObject> object( component.create() ); + QVERIFY(object != 0); + + QCOMPARE( object->property("state").toString(), QStringLiteral("MyState2") ); + QQmlListReference list( object.data(), "states"); + QCOMPARE( list.count(), 2 ); + + QQuickState* state1 = dynamic_cast<QQuickState*>( list.at( 0 ) ); + QVERIFY(state1 != 0); + QCOMPARE( state1->name(), QStringLiteral("MyState1") ); + QQuickState* state2 = dynamic_cast<QQuickState*>( list.at( 1 ) ); + QVERIFY(state2 != 0); + + QCOMPARE( state2->name(), QStringLiteral("MyState2") ); +} + + QTEST_MAIN(tst_qqmllistreference) #include "tst_qqmllistreference.moc" diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp index 8d974f4d17..10a3a0bfa8 100644 --- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp @@ -48,7 +48,8 @@ public: TestItem(QQuickItem *parent = 0) : QQuickItem(parent), focused(false), pressCount(0), releaseCount(0) , wheelCount(0), acceptIncomingTouchEvents(true) - , touchEventReached(false), timestamp(0) {} + , touchEventReached(false), timestamp(0) + , lastWheelEventPos(0, 0), lastWheelEventGlobalPos(0, 0) {} bool focused; int pressCount; @@ -57,6 +58,8 @@ public: bool acceptIncomingTouchEvents; bool touchEventReached; ulong timestamp; + QPoint lastWheelEventPos; + QPoint lastWheelEventGlobalPos; protected: virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; } virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; } @@ -66,7 +69,13 @@ protected: touchEventReached = true; event->setAccepted(acceptIncomingTouchEvents); } - virtual void wheelEvent(QWheelEvent *event) { event->accept(); ++wheelCount; timestamp = event->timestamp(); } + virtual void wheelEvent(QWheelEvent *event) { + event->accept(); + ++wheelCount; + timestamp = event->timestamp(); + lastWheelEventPos = event->pos(); + lastWheelEventGlobalPos = event->globalPos(); + } }; class TestWindow: public QQuickWindow @@ -1422,19 +1431,24 @@ void tst_qquickitem::wheelEvent() const bool shouldReceiveWheelEvents = visible && enabled; + const int width = 200; + const int height = 200; + QQuickWindow window; - window.resize(200, 200); + window.resize(width, height); window.show(); QTest::qWaitForWindowExposed(&window); TestItem *item = new TestItem; - item->setSize(QSizeF(200, 100)); + item->setSize(QSizeF(width, height)); item->setParentItem(window.contentItem()); item->setEnabled(enabled); item->setVisible(visible); - QWheelEvent event(QPoint(100, 50), -120, Qt::NoButton, Qt::NoModifier, Qt::Vertical); + QPoint localPoint(width / 2, height / 2); + QPoint globalPoint = window.mapToGlobal(localPoint); + QWheelEvent event(localPoint, globalPoint, -120, Qt::NoButton, Qt::NoModifier, Qt::Vertical); event.setTimestamp(123456UL); event.setAccepted(false); QGuiApplication::sendEvent(&window, &event); @@ -1443,6 +1457,8 @@ void tst_qquickitem::wheelEvent() QVERIFY(event.isAccepted()); QCOMPARE(item->wheelCount, 1); QCOMPARE(item->timestamp, 123456UL); + QCOMPARE(item->lastWheelEventPos, localPoint); + QCOMPARE(item->lastWheelEventGlobalPos, globalPoint); } else { QVERIFY(!event.isAccepted()); QCOMPARE(item->wheelCount, 0); diff --git a/tests/auto/quick/qquicklayouts/data/rowlayout/Container2.qml b/tests/auto/quick/qquicklayouts/data/rowlayout/Container2.qml new file mode 100644 index 0000000000..248652e82b --- /dev/null +++ b/tests/auto/quick/qquicklayouts/data/rowlayout/Container2.qml @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Layouts 1.3 + +Item { + objectName: "qtbug51927-container" + visible: true + + default property alias _contents: customContent.data + + ColumnLayout { + id: customContent + objectName: "qtbug51927-columnLayout" + anchors.fill: parent + } +} diff --git a/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser2.qml b/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser2.qml new file mode 100644 index 0000000000..9def782d4a --- /dev/null +++ b/tests/auto/quick/qquicklayouts/data/rowlayout/ContainerUser2.qml @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.6 + +Container2 { + visible: true + Item {} +} diff --git a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml index 97860458fe..4346c5283e 100644 --- a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml +++ b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml @@ -959,5 +959,15 @@ Item { // Shouldn't crash. containerUser.destroy(); } + + function test_defaultPropertyAliasCrashAgain() { + var containerUserComponent = Qt.createComponent("rowlayout/ContainerUser2.qml"); + compare(containerUserComponent.status, Component.Ready); + + var containerUser = createTemporaryObject(containerUserComponent, testCase); + verify(containerUser); + + // Shouldn't crash upon destroying containerUser. + } } } diff --git a/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp index 10d9829520..977c5b6ff1 100644 --- a/tools/qmlcachegen/qmlcachegen.cpp +++ b/tools/qmlcachegen/qmlcachegen.cpp @@ -276,7 +276,9 @@ int main(int argc, char **argv) parser.process(app); const QStringList sources = parser.positionalArguments(); - if (sources.count() > 1) { + if (sources.isEmpty()){ + parser.showHelp(); + } else if (sources.count() > 1) { fprintf(stderr, "%s\n", qPrintable(QStringLiteral("Too many input files specified: '") + sources.join(QStringLiteral("' '")) + QLatin1Char('\''))); return EXIT_FAILURE; } diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp index 897902b26f..26a83395c8 100644 --- a/tools/qmlimportscanner/main.cpp +++ b/tools/qmlimportscanner/main.cpp @@ -539,7 +539,7 @@ int main(int argc, char *argv[]) if (arg.startsWith(QLatin1Char('-')) && arg != QLatin1String("-")) break; ++i; - if (!QFile::exists(arg)) { + if (arg != QLatin1String("-") && !QFile::exists(arg)) { std::cerr << qPrintable(appName) << ": No such file or directory: \"" << qPrintable(arg) << "\"\n"; return 1; diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp index 774be45aec..acd892bedb 100644 --- a/tools/qmlplugindump/main.cpp +++ b/tools/qmlplugindump/main.cpp @@ -839,7 +839,8 @@ static bool getDependencies(const QQmlEngine &engine, const QString &pluginImpor QStringList commandArgs = QStringList() << QLatin1String("-qmlFiles") << QLatin1String("-"); - const auto importPathList = engine.importPathList(); + QStringList importPathList = engine.importPathList(); + importPathList.removeOne(QStringLiteral("qrc:/qt-project.org/imports")); for (const QString &path : importPathList) commandArgs << QLatin1String("-importPath") << path; @@ -866,6 +867,8 @@ static bool getDependencies(const QQmlEngine &engine, const QString &pluginImpor if (!readDependenciesData(QLatin1String("<outputOfQmlimportscanner>"), depencenciesData, dependencies, QStringList(pluginImportUri), forceQtQuickDependency)) { std::cerr << "failed to proecess output of qmlimportscanner" << std::endl; + if (importScanner.exitCode() != 0) + std::cerr << importScanner.readAllStandardError().toStdString(); return false; } |