Merge remote-tracking branch 'origin/5.9' into dev

Change-Id: I92b13a9c1727644d63e125c1e6f1fdac72720ad7
This commit is contained in:
Liang Qi 2017-02-28 13:04:16 +01:00
commit afec9016d0
51 changed files with 577 additions and 107 deletions

View File

@ -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();

View File

@ -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();
}

View File

@ -53,7 +53,6 @@
#include "qquickparticlepainter_p.h"
#include <private/qquickopenglshadereffectnode_p.h>
#include <private/qquickopenglshadereffect_p.h>
#include <QSignalMapper>
QT_BEGIN_NAMESPACE

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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.)

View File

@ -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();

View File

@ -1575,7 +1575,7 @@ static void longestAvailableReg(int *nextUses, int nextUseCount, int &reg, 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;

View File

@ -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;

View File

@ -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());

View File

@ -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); }

View File

@ -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;
}
}

View File

@ -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());

View File

@ -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);

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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";

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -70,7 +70,6 @@ QT_REQUIRE_CONFIG(quick_shadereffect);
QT_BEGIN_NAMESPACE
class QSGContext;
class QSignalMapper;
class QFileSelector;
class QQuickOpenGLCustomMaterialShader;

View File

@ -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();

View File

@ -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"

View File

@ -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

View File

@ -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()
{

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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";
}
}

View File

@ -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

View File

@ -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"

View File

@ -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);

View File

@ -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
}
}

View File

@ -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 {}
}

View File

@ -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.
}
}
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}