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

Change-Id: I1e1d9585d876a8eacd4c24afc894a33075f51a13
This commit is contained in:
Qt Forward Merge Bot 2020-01-30 01:00:57 +01:00
commit 5be153af99
55 changed files with 561 additions and 141 deletions

89
dist/changes-5.14.1 vendored Normal file
View File

@ -0,0 +1,89 @@
Qt 5.14.1 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with Qt 5.14.0.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qt-5/index.html
The Qt version 5.14 series is binary compatible with the 5.13.x series.
Applications compiled for 5.13 will continue to run with 5.14.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* QtQml *
****************************************************************************
- [QTBUG-81109] Don't crash when iterating invalid Proxy objects
- [QTBUG-81108] Don't crash when sorting arrays with non-stringifyable entries
- [QTBUG-81105] Support printing arrays with circular references
- [QTBUG-81104] Array.includes now works even with large arrays.
- [QTBUG-81037] Fixed oob access on Array.concat.
- [QTBUG-81093] Emit QQmlEngine::warnings when load fails instead of
simply qWarning.
- [QTBUG-81055] XMLHttpRequest works correctly in a QML WorkerThread.
- [QTBUG-80963] Fixed a crash in QQmlAdaptorModel.
- [QTBUG-80609] Fixed a crash related to the use of QSequentialIterable
as a JS container type.
- [QTBUG-80511] The compiler now supports larger stack slots to avoid
crashing when passing long lists or vectors.
- [QTBUG-30467] QQmlTypeLoader no longer parses qmldir content multiple times.
It can be told to forget the qmldir contents via QQmlTypeLoader::clearCache(),
as before.
****************************************************************************
* QtQuick *
****************************************************************************
- [QTBUG-71193] Fixed two crashes and a memory leak in ItemParticle.
- [QTBUG-34779] Fixed a crash in QQuickWindow that was discovered during
fuzz testing.
- [QTBUG-80505] TableView now resets its content size to empty if the
model becomes empty.
- [QTBUG-80505][QTBUG-71374] Fixed crashes in TableView when deleting or
setting the model to null.
- [QTBUG-80534] TableView behaves better when both a delegate and an
ObjectModel or DelegateModel are declared.
- [QTBUG-67986] ObjectModel items are now re-rendered when moved between models.
- [QTBUG-78297] DelegateModel and DelegateChoice now work together better.
- [QTBUG-79163] If a MouseArea has its preventStealing flag set,
a Pointer Handler that is a child is not allowed to steal the grab.
- [QTBUG-77624] MouseArea now reacts to touch ungrab, so that it will
know the interaction has been cancelled if the user begins dragging
after the press, and a DragHandler takes over.
- [QTBUG-68232] ListView now emits currentIndexChanged (to indicate a
value of -1) if an empty model is assigned.
- [QTBUG-66163] If the populate animation runs as a result of model assignment,
the viewport should not move.
- [QTBUG-79592] PathView now continues animating to the nearest
detent, as usual, when ungrabMouse() is called.
- [QTBUG-76954] Multiple TapHandlers (again) are able to react to
multiple touchpoints simultaneously, without losing the active state
when one of the points is stationary.
- [QTBUG-64138] Particle effects can now run continuously over longer
periods of time.
- [QTBUG-80190] We no longer emit TextInput.inputMaskChanged when you are
setting the same input mask again.
- [QTBUG-80070] When an animation is set on an Item which is loaded by a
Loader, it will no longer crash when the animation is deleted.
- [QTBUG-80364] Attempting to call QSGTexture::bind() outside the direct
OpenGL rendering path now generates a warning.
- [QTBUG-80297] QRhi now follows non-integer scaling fixes for native text.
- [QTBUG-75750] MultiPointTouchArea no longer ignores Qt-synthesized mouse
events. It's now possible to use a stylus with Qt Virtual Keyboard
because MPTA will react to the synth-mouse event that occurs after the
QTabletEvent was not handled. In the case that a touch event is sent,
MPTA will accept it; so a synth-mouse event is not expected afterwards.
If Flickable has pressDelay set, and intercepts a touch press, it will
send the delayed press in the form of a mouse press, and MPTA will now
react, which is useful in case MPTA is used in an item view delegate.
But it will also receive a touch release after the synthetic delayed press,
so now it checks whether the touchpoint ID is the same as the synth-mouse
touch ID, to verify that the touch release corresponds with the synth-mouse
press that arrived earlier, and react to it.

View File

@ -65,7 +65,7 @@ Rectangle {
strokeWidth: 1
fillColor: "black"
PathText { x: 0; y: 100; font.family: "Arial"; font.pixelSize: 150; text: "Qt!" }
PathText { x: 0; y: 0; font.family: "Arial"; font.pixelSize: 150; text: "Qt!" }
}
}
}

View File

@ -94,9 +94,12 @@ qint64 NullDevice::writeData(const char *data, qint64 len)
// (otherwise we assert in QVariant::operator<< when actually saving it)
static bool isSaveable(const QVariant &value)
{
const int valType = static_cast<int>(value.userType());
if (valType >= QMetaType::User)
return false;
NullDevice nullDevice;
QDataStream fakeStream(&nullDevice);
return QMetaType::save(fakeStream, static_cast<int>(value.userType()), value.constData());
return QMetaType::save(fakeStream, valType, value.constData());
}
QQmlEngineDebugServiceImpl::QQmlEngineDebugServiceImpl(QObject *parent) :

View File

@ -362,7 +362,7 @@ ReturnedValue ArrayPrototype::method_toString(const FunctionObject *builtin, con
ScopedString string(scope, scope.engine->newString(QStringLiteral("join")));
ScopedFunctionObject f(scope, that->get(string));
if (f)
return f->call(that, argv, argc);
return checkedResult(scope.engine, f->call(that, argv, argc));
return ObjectPrototype::method_toString(builtin, that, argv, argc);
}
@ -1209,6 +1209,7 @@ ReturnedValue ArrayPrototype::method_every(const FunctionObject *b, const Value
arguments[1] = Value::fromDouble(k);
arguments[2] = instance;
r = callback->call(that, arguments, 3);
CHECK_EXCEPTION();
ok = r->toBoolean();
}
return Encode(ok);
@ -1276,6 +1277,7 @@ ReturnedValue ArrayPrototype::method_some(const FunctionObject *b, const Value *
arguments[1] = Value::fromDouble(k);
arguments[2] = instance;
result = callback->call(that, arguments, 3);
CHECK_EXCEPTION();
if (result->toBoolean())
return Encode(true);
}
@ -1345,6 +1347,7 @@ ReturnedValue ArrayPrototype::method_map(const FunctionObject *b, const Value *t
arguments[1] = Value::fromDouble(k);
arguments[2] = instance;
mapped = callback->call(that, arguments, 3);
CHECK_EXCEPTION();
a->arraySet(k, mapped);
}
return a.asReturnedValue();
@ -1380,6 +1383,7 @@ ReturnedValue ArrayPrototype::method_filter(const FunctionObject *b, const Value
arguments[1] = Value::fromDouble(k);
arguments[2] = instance;
selected = callback->call(that, arguments, 3);
CHECK_EXCEPTION();
if (selected->toBoolean()) {
a->arraySet(to, arguments[0]);
++to;
@ -1430,6 +1434,7 @@ ReturnedValue ArrayPrototype::method_reduce(const FunctionObject *b, const Value
arguments[2] = Value::fromDouble(k);
arguments[3] = instance;
acc = callback->call(nullptr, arguments, 4);
CHECK_EXCEPTION();
}
++k;
}
@ -1483,6 +1488,7 @@ ReturnedValue ArrayPrototype::method_reduceRight(const FunctionObject *b, const
arguments[2] = Value::fromDouble(k - 1);
arguments[3] = instance;
acc = callback->call(nullptr, arguments, 4);
CHECK_EXCEPTION();
}
--k;
}

View File

@ -1561,7 +1561,7 @@ ReturnedValue DatePrototype::method_toJSON(const FunctionObject *b, const Value
if (!toIso)
return v4->throwTypeError();
return toIso->call(O, nullptr, 0);
return checkedResult(v4, toIso->call(O, nullptr, 0));
}
ReturnedValue DatePrototype::method_symbolToPrimitive(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)

View File

@ -358,7 +358,7 @@ ReturnedValue FunctionPrototype::method_apply(const QV4::FunctionObject *b, cons
return v4->throwTypeError();
thisObject = argc ? argv : nullptr;
if (argc < 2 || argv[1].isNullOrUndefined())
return f->call(thisObject, argv, 0);
return checkedResult(v4, f->call(thisObject, argv, 0));
Object *arr = argv[1].objectValue();
if (!arr)
@ -398,13 +398,14 @@ ReturnedValue FunctionPrototype::method_apply(const QV4::FunctionObject *b, cons
}
}
return f->call(thisObject, arguments, len);
return checkedResult(v4, f->call(thisObject, arguments, len));
}
ReturnedValue FunctionPrototype::method_call(const QV4::FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
QV4::ExecutionEngine *v4 = b->engine();
if (!thisObject->isFunctionObject())
return b->engine()->throwTypeError();
return v4->throwTypeError();
const FunctionObject *f = static_cast<const FunctionObject *>(thisObject);
@ -413,7 +414,7 @@ ReturnedValue FunctionPrototype::method_call(const QV4::FunctionObject *b, const
++argv;
--argc;
}
return f->call(thisObject, argv, argc);
return checkedResult(v4, f->call(thisObject, argv, argc));
}
ReturnedValue FunctionPrototype::method_bind(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
@ -713,12 +714,12 @@ void Heap::BoundFunction::init(QV4::ExecutionContext *scope, QV4::FunctionObject
ReturnedValue BoundFunction::virtualCall(const FunctionObject *fo, const Value *, const Value *argv, int argc)
{
const BoundFunction *f = static_cast<const BoundFunction *>(fo);
Scope scope(f->engine());
if (scope.hasException())
QV4::ExecutionEngine *v4 = fo->engine();
if (v4->hasException)
return Encode::undefined();
const BoundFunction *f = static_cast<const BoundFunction *>(fo);
Scope scope(v4);
Scoped<MemberData> boundArgs(scope, f->boundArgs());
ScopedFunctionObject target(scope, f->target());
JSCallData jsCallData(scope, (boundArgs ? boundArgs->size() : 0) + argc);
@ -729,7 +730,7 @@ ReturnedValue BoundFunction::virtualCall(const FunctionObject *fo, const Value *
argp += boundArgs->size();
}
memcpy(argp, argv, argc*sizeof(Value));
return target->call(jsCallData);
return checkedResult(v4, target->call(jsCallData));
}
ReturnedValue BoundFunction::virtualCallAsConstructor(const FunctionObject *fo, const Value *argv, int argc, const Value *)

View File

@ -328,6 +328,10 @@ inline bool FunctionObject::isBoundFunction() const
return d()->vtable() == BoundFunction::staticVTable();
}
inline ReturnedValue checkedResult(QV4::ExecutionEngine *v4, ReturnedValue result)
{
return v4->hasException ? QV4::Encode::undefined() : result;
}
}

View File

@ -703,6 +703,8 @@ QString Stringify::Str(const QString &key, const Value &v)
*jsCallData->thisObject = value;
jsCallData->args[0] = v4->newString(key);
value = toJSON->call(jsCallData);
if (v4->hasException)
return QString();
}
}
@ -714,6 +716,8 @@ QString Stringify::Str(const QString &key, const Value &v)
jsCallData->args[1] = value;
*jsCallData->thisObject = holder;
value = replacerFunction->call(jsCallData);
if (v4->hasException)
return QString();
}
o = value->asReturnedValue();

View File

@ -309,7 +309,8 @@ ReturnedValue Lookup::getterAccessor(Lookup *l, ExecutionEngine *engine, const V
if (!getter->isFunctionObject()) // ### catch at resolve time
return Encode::undefined();
return static_cast<const FunctionObject *>(getter)->call(&object, nullptr, 0);
return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call(
&object, nullptr, 0));
}
}
l->getter = getterFallback;
@ -326,7 +327,8 @@ ReturnedValue Lookup::getterProtoAccessor(Lookup *l, ExecutionEngine *engine, co
if (!getter->isFunctionObject()) // ### catch at resolve time
return Encode::undefined();
return static_cast<const FunctionObject *>(getter)->call(&object, nullptr, 0);
return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call(
&object, nullptr, 0));
}
return getterTwoClasses(l, engine, object);
}
@ -346,7 +348,8 @@ ReturnedValue Lookup::getterProtoAccessorTwoClasses(Lookup *l, ExecutionEngine *
if (!getter->isFunctionObject()) // ### catch at resolve time
return Encode::undefined();
return static_cast<const FunctionObject *>(getter)->call(&object, nullptr, 0);
return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call(
&object, nullptr, 0));
}
}
l->getter = getterFallback;
@ -391,7 +394,8 @@ ReturnedValue Lookup::primitiveGetterAccessor(Lookup *l, ExecutionEngine *engine
if (!getter->isFunctionObject()) // ### catch at resolve time
return Encode::undefined();
return static_cast<const FunctionObject *>(getter)->call(&object, nullptr, 0);
return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call(
&object, nullptr, 0));
}
}
l->getter = getterGeneric;
@ -429,7 +433,8 @@ ReturnedValue Lookup::globalGetterProtoAccessor(Lookup *l, ExecutionEngine *engi
if (!getter->isFunctionObject()) // ### catch at resolve time
return Encode::undefined();
return static_cast<const FunctionObject *>(getter)->call(engine->globalObject, nullptr, 0);
return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call(
engine->globalObject, nullptr, 0));
}
l->globalGetter = globalGetterGeneric;
return globalGetterGeneric(l, engine);

View File

@ -105,7 +105,7 @@ ReturnedValue Object::getValueAccessor(const Value *thisObject, const Value &v,
JSCallData jsCallData(scope);
if (thisObject)
*jsCallData->thisObject = *thisObject;
return f->call(jsCallData);
return checkedResult(scope.engine, f->call(jsCallData));
}
bool Object::putValue(uint memberIndex, PropertyAttributes attrs, const Value &value)

View File

@ -667,7 +667,7 @@ ReturnedValue ObjectPrototype::method_toLocaleString(const FunctionObject *b, co
if (!f)
THROW_TYPE_ERROR();
return f->call(thisObject, argv, argc);
return checkedResult(scope.engine, f->call(thisObject, argv, argc));
}
ReturnedValue ObjectPrototype::method_valueOf(const FunctionObject *b, const Value *thisObject, const Value *, int)

View File

@ -618,7 +618,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this
}
ScopedObject nextPromise(scope, Value::fromReturnedValue(resolve->call(thisObject, nextValue, 1)));
if (!nextPromise || scope.hasException()) {
if (scope.hasException() || !nextPromise) {
ScopedValue completion(scope, Runtime::IteratorClose::call(e, iteratorObject, doneValue));
if (scope.hasException()) {
completion = e->exceptionValue->asReturnedValue();
@ -764,7 +764,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi
}
ScopedObject nextPromise(scope, Value::fromReturnedValue(resolve->call(thisObject, nextValue, 1)));
if (!nextPromise || scope.hasException()) {
if (scope.hasException() || !nextPromise) {
ScopedValue completion(scope, Runtime::IteratorClose::call(e, iteratorObject, doneValue));
if (scope.hasException()) {
completion = e->exceptionValue->asReturnedValue();

View File

@ -96,6 +96,8 @@ ReturnedValue ProxyObject::virtualGet(const Managed *m, PropertyKey id, const Va
cdata.args[2] = *receiver;
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (scope.engine->hasException)
return Encode::undefined();
ScopedProperty targetDesc(scope);
PropertyAttributes attributes = target->getOwnProperty(id, targetDesc);
if (attributes != Attr_Invalid && !attributes.isConfigurable()) {
@ -136,7 +138,7 @@ bool ProxyObject::virtualPut(Managed *m, PropertyKey id, const Value &value, Val
cdata.args[3] = *receiver;
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (!trapResult->toBoolean())
if (scope.engine->hasException || !trapResult->toBoolean())
return false;
ScopedProperty targetDesc(scope);
PropertyAttributes attributes = target->getOwnProperty(id, targetDesc);
@ -176,7 +178,7 @@ bool ProxyObject::virtualDeleteProperty(Managed *m, PropertyKey id)
cdata.args[2] = o->d(); // ### fix receiver handling
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (!trapResult->toBoolean())
if (scope.engine->hasException || !trapResult->toBoolean())
return false;
ScopedProperty targetDesc(scope);
PropertyAttributes attributes = target->getOwnProperty(id, targetDesc);
@ -211,6 +213,8 @@ bool ProxyObject::virtualHasProperty(const Managed *m, PropertyKey id)
cdata.args[1] = id.isArrayIndex() ? Value::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asStringOrSymbol();
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (scope.engine->hasException)
return false;
bool result = trapResult->toBoolean();
if (!result) {
ScopedProperty targetDesc(scope);
@ -251,6 +255,8 @@ PropertyAttributes ProxyObject::virtualGetOwnProperty(const Managed *m, Property
cdata.args[1] = id.isArrayIndex() ? Value::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asStringOrSymbol();
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (scope.engine->hasException)
return Attr_Invalid;
if (!trapResult->isObject() && !trapResult->isUndefined()) {
scope.engine->throwTypeError();
return Attr_Invalid;
@ -323,7 +329,7 @@ bool ProxyObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Pro
cdata.args[2] = ObjectPrototype::fromPropertyDescriptor(scope.engine, p, attrs);
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
bool result = trapResult->toBoolean();
bool result = !scope.engine->hasException && trapResult->toBoolean();
if (!result)
return false;
@ -373,6 +379,8 @@ bool ProxyObject::virtualIsExtensible(const Managed *m)
cdata.args[0] = target;
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (scope.engine->hasException)
return false;
bool result = trapResult->toBoolean();
if (result != target->isExtensible()) {
scope.engine->throwTypeError();
@ -404,6 +412,8 @@ bool ProxyObject::virtualPreventExtensions(Managed *m)
cdata.args[0] = target;
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (scope.engine->hasException)
return false;
bool result = trapResult->toBoolean();
if (result && target->isExtensible()) {
scope.engine->throwTypeError();
@ -439,6 +449,8 @@ Heap::Object *ProxyObject::virtualGetPrototypeOf(const Managed *m)
cdata.args[0] = target;
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (scope.engine->hasException)
return nullptr;
if (!trapResult->isNull() && !trapResult->isObject()) {
scope.engine->throwTypeError();
return nullptr;
@ -482,7 +494,7 @@ bool ProxyObject::virtualSetPrototypeOf(Managed *m, const Object *p)
cdata.args[1] = p ? p->asReturnedValue() : Encode::null();
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
bool result = trapResult->toBoolean();
bool result = !scope.engine->hasException && trapResult->toBoolean();
if (!result)
return false;
if (!target->isExtensible()) {
@ -573,6 +585,8 @@ OwnPropertyKeyIterator *ProxyObject::virtualOwnPropertyKeys(const Object *m, Val
JSCallData cdata(scope, 1, nullptr, handler);
cdata.args[0] = target;
ScopedObject trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (scope.engine->hasException)
return nullptr;
if (!trapResult) {
scope.engine->throwTypeError();
return nullptr;
@ -699,7 +713,7 @@ ReturnedValue ProxyFunctionObject::virtualCall(const FunctionObject *f, const Va
if (scope.hasException())
return Encode::undefined();
if (trap->isNullOrUndefined())
return target->call(thisObject, argv, argc);
return checkedResult(scope.engine, target->call(thisObject, argv, argc));
if (!trap->isFunctionObject())
return scope.engine->throwTypeError();

View File

@ -98,7 +98,8 @@ ReturnedValue Reflect::method_apply(const FunctionObject *f, const Value *, cons
if (scope.hasException())
return Encode::undefined();
return static_cast<const FunctionObject &>(argv[0]).call(&argv[1], arguments.argv, arguments.argc);
return checkedResult(scope.engine, static_cast<const FunctionObject &>(argv[0]).call(
&argv[1], arguments.argv, arguments.argc));
}
ReturnedValue Reflect::method_construct(const FunctionObject *f, const Value *, const Value *argv, int argc)

View File

@ -481,6 +481,8 @@ ReturnedValue RegExpPrototype::exec(ExecutionEngine *engine, const Object *o, co
ScopedFunctionObject exec(scope, o->get(key));
if (exec) {
ScopedValue result(scope, exec->call(o, s, 1));
if (scope.hasException())
RETURN_UNDEFINED();
if (!result->isNull() && !result->isObject())
return scope.engine->throwTypeError();
return result->asReturnedValue();
@ -737,6 +739,8 @@ ReturnedValue RegExpPrototype::method_replace(const FunctionObject *f, const Val
cData->args[nCaptures + 1] = Encode(position);
cData->args[nCaptures + 2] = s;
ScopedValue replValue(scope, replaceFunction->call(cData));
if (scope.hasException())
return Encode::undefined();
replacement = replValue->toQString();
} else {
replacement = RegExp::getSubstitution(matchString->toQString(), s->toQString(), position, cData.args, nCaptures, replaceValue->toQString());

View File

@ -390,7 +390,7 @@ QV4::ReturnedValue Runtime::Instanceof::call(ExecutionEngine *engine, const Valu
return engine->throwTypeError();
ScopedValue result(scope, fHasInstance->call(&rval, &lval, 1));
return Encode(result->toBoolean());
return scope.hasException() ? Encode::undefined() : Encode(result->toBoolean());
}
QV4::ReturnedValue Runtime::In::call(ExecutionEngine *engine, const Value &left, const Value &right)
@ -515,6 +515,8 @@ ReturnedValue RuntimeHelpers::ordinaryToPrimitive(ExecutionEngine *engine, const
ScopedValue conv(scope, object->get(meth1));
if (FunctionObject *o = conv->as<FunctionObject>()) {
result = o->call(object, nullptr, 0);
if (engine->hasException)
return Encode::undefined();
if (result->isPrimitive())
return result->asReturnedValue();
}
@ -525,6 +527,8 @@ ReturnedValue RuntimeHelpers::ordinaryToPrimitive(ExecutionEngine *engine, const
conv = object->get(meth2);
if (FunctionObject *o = conv->as<FunctionObject>()) {
result = o->call(object, nullptr, 0);
if (engine->hasException)
return Encode::undefined();
if (result->isPrimitive())
return result->asReturnedValue();
}
@ -800,6 +804,8 @@ ReturnedValue Runtime::GetIterator::call(ExecutionEngine *engine, const Value &i
return engine->throwTypeError();
JSCallData cData(scope, 0, nullptr, o);
ScopedObject it(scope, f->call(cData));
if (engine->hasException)
return Encode::undefined();
if (!it)
return engine->throwTypeError();
return it->asReturnedValue();
@ -1341,7 +1347,8 @@ ReturnedValue Runtime::CallGlobalLookup::call(ExecutionEngine *engine, uint inde
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]->toQString());
}
return static_cast<FunctionObject &>(function).call(&thisObject, argv, argc);
return checkedResult(engine, static_cast<FunctionObject &>(function).call(
&thisObject, argv, argc));
}
ReturnedValue Runtime::CallQmlContextPropertyLookup::call(ExecutionEngine *engine, uint index,
@ -1356,7 +1363,8 @@ ReturnedValue Runtime::CallQmlContextPropertyLookup::call(ExecutionEngine *engin
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]->toQString());
}
return static_cast<FunctionObject &>(function).call(thisObject, argv, argc);
return checkedResult(engine, static_cast<FunctionObject &>(function).call(
thisObject, argv, argc));
}
ReturnedValue Runtime::CallPossiblyDirectEval::call(ExecutionEngine *engine, Value *argv, int argc)
@ -1375,7 +1383,7 @@ ReturnedValue Runtime::CallPossiblyDirectEval::call(ExecutionEngine *engine, Val
if (function->d() == engine->evalFunction()->d())
return static_cast<EvalFunction *>(function.getPointer())->evalCall(thisObject, argv, argc, true);
return function->call(thisObject, argv, argc);
return checkedResult(engine, function->call(thisObject, argv, argc));
}
ReturnedValue Runtime::CallName::call(ExecutionEngine *engine, int nameIndex, Value *argv, int argc)
@ -1395,7 +1403,7 @@ ReturnedValue Runtime::CallName::call(ExecutionEngine *engine, int nameIndex, Va
->runtimeStrings[nameIndex]->toQString());
}
return f->call(thisObject, argv, argc);
return checkedResult(engine, f->call(thisObject, argv, argc));
}
ReturnedValue Runtime::CallProperty::call(ExecutionEngine *engine, const Value &baseRef, int nameIndex, Value *argv, int argc)
@ -1437,7 +1445,7 @@ ReturnedValue Runtime::CallProperty::call(ExecutionEngine *engine, const Value &
return engine->throwTypeError(error);
}
return f->call(base, argv, argc);
return checkedResult(engine, f->call(base, argv, argc));
}
ReturnedValue Runtime::CallPropertyLookup::call(ExecutionEngine *engine, const Value &base, uint index, Value *argv, int argc)
@ -1449,7 +1457,7 @@ ReturnedValue Runtime::CallPropertyLookup::call(ExecutionEngine *engine, const V
if (!f.isFunctionObject())
return engine->throwTypeError();
return static_cast<FunctionObject &>(f).call(&base, argv, argc);
return checkedResult(engine, static_cast<FunctionObject &>(f).call(&base, argv, argc));
}
ReturnedValue Runtime::CallElement::call(ExecutionEngine *engine, const Value &baseRef, const Value &index, Value *argv, int argc)
@ -1467,7 +1475,7 @@ ReturnedValue Runtime::CallElement::call(ExecutionEngine *engine, const Value &b
if (!f)
return engine->throwTypeError();
return f->call(base, argv, argc);
return checkedResult(engine, f->call(base, argv, argc));
}
ReturnedValue Runtime::CallValue::call(ExecutionEngine *engine, const Value &func, Value *argv, int argc)
@ -1475,7 +1483,8 @@ ReturnedValue Runtime::CallValue::call(ExecutionEngine *engine, const Value &fun
if (!func.isFunctionObject())
return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow()));
Value undef = Value::undefinedValue();
return static_cast<const FunctionObject &>(func).call(&undef, argv, argc);
return checkedResult(engine, static_cast<const FunctionObject &>(func).call(
&undef, argv, argc));
}
ReturnedValue Runtime::CallWithReceiver::call(ExecutionEngine *engine, const Value &func,
@ -1483,7 +1492,8 @@ ReturnedValue Runtime::CallWithReceiver::call(ExecutionEngine *engine, const Val
{
if (!func.isFunctionObject())
return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow()));
return static_cast<const FunctionObject &>(func).call(&thisObject, argv, argc);
return checkedResult(engine, static_cast<const FunctionObject &>(func).call(
&thisObject, argv, argc));
}
struct CallArgs {
@ -1537,7 +1547,8 @@ ReturnedValue Runtime::CallWithSpread::call(ExecutionEngine *engine, const Value
if (engine->hasException)
return Encode::undefined();
return static_cast<const FunctionObject &>(function).call(&thisObject, arguments.argv, arguments.argc);
return checkedResult(engine, static_cast<const FunctionObject &>(function).call(
&thisObject, arguments.argv, arguments.argc));
}
ReturnedValue Runtime::Construct::call(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc)
@ -1580,7 +1591,7 @@ ReturnedValue Runtime::TailCall::call(CppStackFrame *frame, ExecutionEngine *eng
if (!frame->callerCanHandleTailCall || !fo.canBeTailCalled() || engine->debugger()
|| unsigned(argc) > fo.formalParameterCount()) {
// Cannot tailcall, do a normal call:
return fo.call(&thisObject, argv, argc);
return checkedResult(engine, fo.call(&thisObject, argv, argc));
}
memcpy(frame->jsFrame->args, argv, argc * sizeof(Value));

View File

@ -591,7 +591,7 @@ ReturnedValue StringPrototype::method_match(const FunctionObject *b, const Value
ScopedFunctionObject match(scope, that->get(scope.engine->symbol_match()));
if (!match)
return scope.engine->throwTypeError();
return match->call(that, s, 1);
return checkedResult(scope.engine, match->call(that, s, 1));
}
ReturnedValue StringPrototype::method_normalize(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)

View File

@ -763,6 +763,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_every(const FunctionObject *b
arguments[1] = Value::fromDouble(k);
arguments[2] = v;
r = callback->call(that, arguments, 3);
CHECK_EXCEPTION();
ok = r->toBoolean();
}
return Encode(ok);
@ -862,6 +863,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_filter(const FunctionObject *
arguments[1] = Value::fromDouble(k);
arguments[2] = instance;
selected = callback->call(that, arguments, 3);
CHECK_EXCEPTION();
if (selected->toBoolean()) {
++arguments;
scope.alloc(1);
@ -1194,6 +1196,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_map(const FunctionObject *b,
arguments[1] = Value::fromDouble(k);
arguments[2] = instance;
mapped = callback->call(that, arguments, 3);
CHECK_EXCEPTION();
a->put(k, mapped);
}
return a->asReturnedValue();
@ -1243,6 +1246,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_reduce(const FunctionObject *
arguments[2] = Value::fromDouble(k);
arguments[3] = instance;
acc = callback->call(nullptr, arguments, 4);
CHECK_EXCEPTION();
}
++k;
}
@ -1298,6 +1302,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_reduceRight(const FunctionObj
arguments[2] = Value::fromDouble(k - 1);
arguments[3] = instance;
acc = callback->call(nullptr, arguments, 4);
CHECK_EXCEPTION();
}
--k;
}
@ -1359,6 +1364,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_some(const FunctionObject *b,
arguments[1] = Value::fromDouble(k);
arguments[2] = instance;
result = callback->call(that, arguments, 3);
CHECK_EXCEPTION();
if (result->toBoolean())
return Encode(true);
}

View File

@ -1247,6 +1247,31 @@ UiObjectMember: T_DEFAULT UiObjectMemberListPropertyNoInitialiser;
} break;
./
UiObjectMember: T_DEFAULT T_REQUIRED UiObjectMemberPropertyNoInitialiser;
/.
case $rule_number: {
AST::UiPublicMember *node = sym(3).UiPublicMember;
node->isDefaultMember = true;
node->defaultToken = loc(1);
node->isRequired = true;
node->requiredToken = loc(2);
sym(1).Node = node;
} break;
./
UiObjectMember: T_REQUIRED T_DEFAULT UiObjectMemberPropertyNoInitialiser;
/.
case $rule_number: {
AST::UiPublicMember *node = sym(3).UiPublicMember;
node->isDefaultMember = true;
node->defaultToken = loc(2);
node->isRequired = true;
node->requiredToken = loc(1);
sym(1).Node = node;
} break;
./
OptionalSemicolon: | Semicolon;
/.
/* we need OptionalSemicolon because UiScriptStatement might already parse the last semicolon

View File

@ -1515,6 +1515,14 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
}
}
for (int i = 0; i <= _propertyCache->propertyOffset(); ++i) {
QQmlPropertyData *propertyData = _propertyCache->property(i);
if (propertyData && propertyData->isRequired()) {
sharedState->hadRequiredProperties = true;
sharedState->requiredProperties.insert(propertyData, RequiredPropertyInfo {propertyData->name(_qobject), compilationUnit->finalUrl(), _compiledObject->location, {}});
}
}
if (_compiledObject->nFunctions > 0)
setupFunctions();
setupBindings();

View File

@ -75,6 +75,7 @@ static QQmlPropertyData::Flags fastFlagsForProperty(const QMetaProperty &p)
flags.setIsWritable(p.isWritable());
flags.setIsResettable(p.isResettable());
flags.setIsFinal(p.isFinal());
flags.setIsRequired(p.isRequired());
if (p.isEnumType())
flags.type = QQmlPropertyData::Flags::EnumType;

View File

@ -109,7 +109,7 @@ public:
unsigned isFinalORisV4Function : 1; // Has FINAL flag OR Function takes QQmlV4Function* args
unsigned isSignalHandler : 1; // Function is a signal handler
unsigned isOverload : 1; // Function is an overload of another function
unsigned isCloned : 1; // The function was marked as cloned
unsigned isRequiredORisCloned : 1; // Has REQUIRED flag OR The function was marked as cloned
unsigned isConstructor : 1; // The function was marked is a constructor
unsigned isDirect : 1; // Exists on a C++ QMetaObject
unsigned isOverridden : 1; // Is overridden by a extension property
@ -159,6 +159,11 @@ public:
isDirect = b;
}
void setIsRequired(bool b) {
Q_ASSERT(type != FunctionType);
isRequiredORisCloned = b;
}
void setIsVMEFunction(bool b) {
Q_ASSERT(type == FunctionType);
isConstantORisVMEFunction = b;
@ -193,7 +198,7 @@ public:
void setIsCloned(bool b) {
Q_ASSERT(type == FunctionType);
isCloned = b;
isRequiredORisCloned = b;
}
void setIsConstructor(bool b) {
@ -224,6 +229,7 @@ public:
bool isFinal() const { return !isFunction() && m_flags.isFinalORisV4Function; }
bool isOverridden() const { return m_flags.isOverridden; }
bool isDirect() const { return m_flags.isOverload; }
bool isRequired() const { return !isFunction() && m_flags.isRequiredORisCloned; }
bool hasStaticMetaCallFunction() const { return staticMetaCallFunction() != nullptr; }
bool isFunction() const { return m_flags.type == Flags::FunctionType; }
bool isQObject() const { return m_flags.type == Flags::QObjectDerivedType; }
@ -241,7 +247,7 @@ public:
bool isSignalHandler() const { return m_flags.isSignalHandler; }
bool isOverload() const { return m_flags.isOverload; }
void setOverload(bool onoff) { m_flags.isOverload = onoff; }
bool isCloned() const { return isFunction() && m_flags.isCloned; }
bool isCloned() const { return isFunction() && m_flags.isRequiredORisCloned; }
bool isConstructor() const { return m_flags.isConstructor; }
bool hasOverride() const { return overrideIndex() >= 0; }
@ -438,7 +444,7 @@ QQmlPropertyData::Flags::Flags()
, isFinalORisV4Function(false)
, isSignalHandler(false)
, isOverload(false)
, isCloned(false)
, isRequiredORisCloned(false)
, isConstructor(false)
, isOverridden(false)
, type(OtherType)
@ -455,7 +461,7 @@ bool QQmlPropertyData::Flags::operator==(const QQmlPropertyData::Flags &other) c
isFinalORisV4Function == other.isFinalORisV4Function &&
isOverridden == other.isOverridden &&
isSignalHandler == other.isSignalHandler &&
isCloned == other.isCloned &&
isRequiredORisCloned == other.isRequiredORisCloned &&
type == other.type &&
isConstructor == other.isConstructor &&
notFullyResolved == other.notFullyResolved &&

View File

@ -93,7 +93,7 @@ class QQmlDMCachedModelData : public QQmlDelegateModelItem
{
public:
QQmlDMCachedModelData(
QQmlDelegateModelItemMetaType *metaType,
const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
VDMModelDelegateDataType *dataType,
int index, int row, int column);
@ -255,7 +255,9 @@ public:
bool hasModelData;
};
QQmlDMCachedModelData::QQmlDMCachedModelData(QQmlDelegateModelItemMetaType *metaType, VDMModelDelegateDataType *dataType, int index, int row, int column)
QQmlDMCachedModelData::QQmlDMCachedModelData(
const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
VDMModelDelegateDataType *dataType, int index, int row, int column)
: QQmlDelegateModelItem(metaType, dataType, index, row, column)
, type(dataType)
{
@ -390,7 +392,7 @@ class QQmlDMAbstractItemModelData : public QQmlDMCachedModelData
public:
QQmlDMAbstractItemModelData(
QQmlDelegateModelItemMetaType *metaType,
const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
VDMModelDelegateDataType *dataType,
int index, int row, int column)
: QQmlDMCachedModelData(metaType, dataType, index, row, column)
@ -512,7 +514,7 @@ public:
QQmlDelegateModelItem *createItem(
QQmlAdaptorModel &model,
QQmlDelegateModelItemMetaType *metaType,
const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
int index, int row, int column) const override
{
VDMAbstractItemModelDataType *dataType = const_cast<VDMAbstractItemModelDataType *>(this);
@ -560,7 +562,7 @@ class QQmlDMListAccessorData : public QQmlDelegateModelItem
Q_OBJECT
Q_PROPERTY(QVariant modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
public:
QQmlDMListAccessorData(QQmlDelegateModelItemMetaType *metaType,
QQmlDMListAccessorData(const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
QQmlAdaptorModel::Accessors *accessor,
int index, int row, int column, const QVariant &value)
: QQmlDelegateModelItem(metaType, accessor, index, row, column)
@ -676,7 +678,7 @@ public:
QQmlDelegateModelItem *createItem(
QQmlAdaptorModel &model,
QQmlDelegateModelItemMetaType *metaType,
const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
int index, int row, int column) const override
{
VDMListDelegateDataType *dataType = const_cast<VDMListDelegateDataType *>(this);
@ -719,7 +721,7 @@ class QQmlDMObjectData : public QQmlDelegateModelItem, public QQmlAdaptorModelPr
Q_INTERFACES(QQmlAdaptorModelProxyInterface)
public:
QQmlDMObjectData(
QQmlDelegateModelItemMetaType *metaType,
const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
VDMObjectDelegateDataType *dataType,
int index, int row, int column,
QObject *object);
@ -790,7 +792,7 @@ public:
QQmlDelegateModelItem *createItem(
QQmlAdaptorModel &model,
QQmlDelegateModelItemMetaType *metaType,
const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
int index, int row, int column) const override
{
VDMObjectDelegateDataType *dataType = const_cast<VDMObjectDelegateDataType *>(this);
@ -930,7 +932,7 @@ public:
VDMObjectDelegateDataType *m_type;
};
QQmlDMObjectData::QQmlDMObjectData(QQmlDelegateModelItemMetaType *metaType,
QQmlDMObjectData::QQmlDMObjectData(const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
VDMObjectDelegateDataType *dataType,
int index, int row, int column,
QObject *object)

View File

@ -87,7 +87,7 @@ public:
virtual QQmlDelegateModelItem *createItem(
QQmlAdaptorModel &,
QQmlDelegateModelItemMetaType *,
const QQmlRefPointer<QQmlDelegateModelItemMetaType> &,
int, int, int) const { return nullptr; }
virtual bool notify(
@ -140,8 +140,11 @@ public:
inline QVariant value(int index, const QString &role) const {
return accessors->value(*this, index, role); }
inline QQmlDelegateModelItem *createItem(QQmlDelegateModelItemMetaType *metaType, int index) {
return accessors->createItem(*this, metaType, index, rowAt(index), columnAt(index)); }
inline QQmlDelegateModelItem *createItem(
const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType, int index)
{
return accessors->createItem(*this, metaType, index, rowAt(index), columnAt(index));
}
inline bool hasProxyObject() const {
return list.type() == QQmlListAccessor::Instance || list.type() == QQmlListAccessor::ListProperty; }

View File

@ -2267,9 +2267,10 @@ void QV4::Heap::QQmlDelegateModelItemObject::destroy()
}
QQmlDelegateModelItem::QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType,
QQmlAdaptorModel::Accessors *accessor,
int modelIndex, int row, int column)
QQmlDelegateModelItem::QQmlDelegateModelItem(
const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
QQmlAdaptorModel::Accessors *accessor,
int modelIndex, int row, int column)
: v4(metaType->v4Engine)
, metaType(metaType)
, contextData(nullptr)
@ -2285,8 +2286,6 @@ QQmlDelegateModelItem::QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *meta
, row(row)
, column(column)
{
metaType->addref();
if (accessor->propertyCache) {
// The property cache in the accessor is common for all the model
// items in the model it wraps. It describes available model roles,
@ -2315,9 +2314,6 @@ QQmlDelegateModelItem::~QQmlDelegateModelItem()
else
delete incubationTask;
}
metaType->release();
}
void QQmlDelegateModelItem::Dispose()

View File

@ -104,7 +104,7 @@ class QQmlDelegateModelItem : public QObject
Q_PROPERTY(int column READ modelColumn NOTIFY columnChanged REVISION 12)
Q_PROPERTY(QObject *model READ modelObject CONSTANT)
public:
QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType,
QQmlDelegateModelItem(const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
QQmlAdaptorModel::Accessors *accessor, int modelIndex,
int row, int column);
~QQmlDelegateModelItem();
@ -148,7 +148,7 @@ public:
static QV4::ReturnedValue get_index(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &arg);
QV4::ExecutionEngine *v4;
QQmlDelegateModelItemMetaType * const metaType;
QQmlRefPointer<QQmlDelegateModelItemMetaType> const metaType;
QQmlContextDataRef contextData;
QPointer<QObject> object;
QPointer<QQmlDelegateModelAttached> attached;

View File

@ -2786,10 +2786,12 @@ bool QQmlListModelParser::applyProperty(
QV4::ScopedContext context(scope, QV4::QmlContext::create(v4->rootContext(), QQmlContextData::get(qmlContext(model->m_modelCache)), nullptr));
QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::createScriptFunction(context, compilationUnit->runtimeFunctions[id]));
QV4::ReturnedValue result = function->call(v4->globalObject, nullptr, 0);
QJSValue v;
QJSValuePrivate::setValue(&v, v4, result);
QV4::ScopedValue result(scope, function->call(v4->globalObject, nullptr, 0));
if (v4->hasException)
v4->catchException();
else
QJSValuePrivate::setValue(&v, v4, result->asReturnedValue());
value.setValue<QJSValue>(v);
} else {
QByteArray script = scriptStr.toUtf8();

View File

@ -78,7 +78,8 @@ void QQmlTableInstanceModel::deleteModelItemLater(QQmlDelegateModelItem *modelIt
QQmlTableInstanceModel::QQmlTableInstanceModel(QQmlContext *qmlContext, QObject *parent)
: QQmlInstanceModel(*(new QObjectPrivate()), parent)
, m_qmlContext(qmlContext)
, m_metaType(new QQmlDelegateModelItemMetaType(m_qmlContext->engine()->handle(), nullptr, QStringList()))
, m_metaType(new QQmlDelegateModelItemMetaType(m_qmlContext->engine()->handle(), nullptr, QStringList()),
QQmlRefPointer<QQmlDelegateModelItemMetaType>::Adopt)
{
}

View File

@ -133,7 +133,7 @@ private:
QQmlAbstractDelegateComponent *m_delegateChooser = nullptr;
QQmlComponent *m_delegate = nullptr;
QPointer<QQmlContext> m_qmlContext;
QQmlDelegateModelItemMetaType *m_metaType;
QQmlRefPointer<QQmlDelegateModelItemMetaType> m_metaType;
QHash<int, QQmlDelegateModelItem *> m_modelItems;
QQmlReusableDelegateModelItemsPool m_reusableItemsPool;

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1" ?>
<catalog>
<book type="Online" wanted="true">
<title>Qt 5 Cadaques</title>
<year>2014</year>
<author>Juergen Bocklage-Ryannel</author>
<author>Johan Thelin</author>
</book>
<book type="Hardcover">
<title>C++ GUI Programming with Qt 4</title>
<year>2006</year>
<author>Jasmin Blanchette</author>
<author>Mark Summerfield</author>
</book>
<book type="Paperback">
<title>Programming with Qt</title>
<year>2002</year>
<author>Matthias Kalle Dalheimer</author>
</book>
</catalog>

View File

@ -197,8 +197,10 @@ void QQuickItemView::setModel(const QVariant &m)
disconnect(d->model, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
disconnect(d->model, SIGNAL(createdItem(int,QObject*)), this, SLOT(createdItem(int,QObject*)));
disconnect(d->model, SIGNAL(destroyingItem(QObject*)), this, SLOT(destroyingItem(QObject*)));
disconnect(d->model, SIGNAL(itemPooled(int, QObject *)), this, SLOT(onItemPooled(int, QObject *)));
disconnect(d->model, SIGNAL(itemReused(int, QObject *)), this, SLOT(onItemReused(int, QObject *)));
if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel*>(d->model)) {
disconnect(delegateModel, SIGNAL(itemPooled(int, QObject *)), this, SLOT(onItemPooled(int, QObject *)));
disconnect(delegateModel, SIGNAL(itemReused(int, QObject *)), this, SLOT(onItemReused(int, QObject *)));
}
}
QQmlInstanceModel *oldModel = d->model;
@ -234,8 +236,10 @@ void QQuickItemView::setModel(const QVariant &m)
connect(d->model, SIGNAL(createdItem(int,QObject*)), this, SLOT(createdItem(int,QObject*)));
connect(d->model, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
connect(d->model, SIGNAL(destroyingItem(QObject*)), this, SLOT(destroyingItem(QObject*)));
connect(d->model, SIGNAL(itemPooled(int, QObject *)), this, SLOT(onItemPooled(int, QObject *)));
connect(d->model, SIGNAL(itemReused(int, QObject *)), this, SLOT(onItemReused(int, QObject *)));
if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel*>(d->model)) {
connect(delegateModel, SIGNAL(itemPooled(int, QObject *)), this, SLOT(onItemPooled(int, QObject *)));
connect(delegateModel, SIGNAL(itemReused(int, QObject *)), this, SLOT(onItemReused(int, QObject *)));
}
if (isComponentComplete()) {
d->updateSectionCriteria();
d->refill();

View File

@ -4694,6 +4694,18 @@ void QQuickTextInput::clear()
These properties hold the padding around the content. This space is reserved
in addition to the contentWidth and contentHeight.
The individual padding properties assume the value of the \c padding
property unless they are set explicitly. For example, if \c padding is
set to \c 4 and \c leftPadding to \c 8, \c 8 will be used as the left
padding.
\note If an explicit width or height is given to a TextInput, care must be
taken to ensure it is large enough to accommodate the relevant padding
values. For example: if \c topPadding and \c bottomPadding are set to
\c 10, but the height of the TextInput is only set to \c 20, the text will
not have enough vertical space in which to be rendered, and will appear
clipped.
*/
qreal QQuickTextInput::padding() const
{

View File

@ -4513,7 +4513,7 @@ QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image, CreateText
}
#if QT_DEPRECATED_SINCE(5, 15)
/*!
Creates a new QSGTexture object from an existing OpenGL texture \a id and \a size.
@ -4535,6 +4535,8 @@ QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image, CreateText
\note This function has no effect when running on the RHI graphics
abstraction. Use createTextureFromNativeObject() instead.
\obsolete
\sa sceneGraphInitialized(), QSGTexture
*/
QSGTexture *QQuickWindow::createTextureFromId(uint id, const QSize &size, CreateTextureOptions options) const
@ -4561,6 +4563,7 @@ QSGTexture *QQuickWindow::createTextureFromId(uint id, const QSize &size, Create
#endif
return nullptr;
}
#endif
/*!
\enum QQuickWindow::NativeObjectType

View File

@ -157,7 +157,12 @@ public:
// Scene graph specific functions
QSGTexture *createTextureFromImage(const QImage &image) const;
QSGTexture *createTextureFromImage(const QImage &image, CreateTextureOptions options) const;
#if QT_DEPRECATED_SINCE(5, 15)
QT_DEPRECATED_X("Use createTextureFromNativeObject() instead")
QSGTexture *createTextureFromId(uint id, const QSize &size, CreateTextureOptions options = CreateTextureOption()) const;
#endif
QSGTexture *createTextureFromNativeObject(NativeObjectType type,
const void *nativeObjectPtr,
int nativeLayout,

View File

@ -2827,11 +2827,11 @@ void QQuickPathText::updatePath() const
if (!_path.isEmpty())
return;
_path.addText(_x, _y, _font, _text);
_path.addText(0.0, 0.0, _font, _text);
// Account for distance from baseline to top, since addText() takes baseline position
QRectF brect = _path.boundingRect();
_path.translate(0.0, -brect.y());
_path.translate(_x, _y - brect.y());
}
void QQuickPathText::addToPath(QPainterPath &path)

View File

@ -1,4 +0,0 @@
[runInterpreted]
macos ci
[runJitted]
macos

View File

@ -0,0 +1,5 @@
import QtQuick 2.15
Item {
required default property Text requiredDefault
}

View File

@ -0,0 +1,5 @@
import QtQuick 2.15
RequiredDefault {
Text {text: "Hello, world!"}
}

View File

@ -0,0 +1,3 @@
import QtQuick 2.15
RequiredDefault { }

View File

@ -0,0 +1,6 @@
import QtQuick 2.15
import qt.test 1.0
RequiredDefaultCpp {
Text {text: "Hello, world!"}
}

View File

@ -0,0 +1,4 @@
import QtQuick 2.15
import qt.test 1.0
RequiredDefaultCpp { }

View File

@ -671,8 +671,20 @@ void tst_qqmlcomponent::setDataNoEngineNoSegfault()
QVERIFY(!c);
}
class RequiredDefaultCpp : public QObject
{
Q_OBJECT
public:
Q_PROPERTY(QQuickItem *defaultProperty MEMBER m_defaultProperty NOTIFY defaultPropertyChanged REQUIRED)
Q_SIGNAL void defaultPropertyChanged();
Q_CLASSINFO("DefaultProperty", "defaultProperty")
private:
QQuickItem *m_defaultProperty = nullptr;
};
void tst_qqmlcomponent::testRequiredProperties_data()
{
qmlRegisterType<RequiredDefaultCpp>("qt.test", 1, 0, "RequiredDefaultCpp");
QTest::addColumn<QUrl>("testFile");
QTest::addColumn<bool>("shouldSucceed");
QTest::addColumn<QString>("errorMsg");
@ -687,6 +699,10 @@ void tst_qqmlcomponent::testRequiredProperties_data()
QTest::addRow("setLater") << testFileUrl("requiredSetLater.qml") << true << "";
QTest::addRow("setViaAliasToSubcomponent") << testFileUrl("setViaAliasToSubcomponent.qml") << true << "";
QTest::addRow("aliasToSubcomponentNotSet") << testFileUrl("aliasToSubcomponentNotSet.qml") << false << "It can be set via the alias property i_alias";
QTest::addRow("required default set") << testFileUrl("requiredDefault.1.qml") << true << "";
QTest::addRow("required default not set") << testFileUrl("requiredDefault.2.qml") << false << "Required property requiredDefault was not initialized";
QTest::addRow("required default set (C++)") << testFileUrl("requiredDefault.3.qml") << true << "";
QTest::addRow("required default not set (C++)") << testFileUrl("requiredDefault.4.qml") << false << "Required property defaultProperty was not initialized";
}

View File

@ -997,6 +997,11 @@ public:
SomeQObjectClass() : QObject(nullptr){}
};
class Dayfly : public QObject
{
Q_OBJECT
};
void tst_qqmlengine::singletonInstance()
{
QQmlEngine engine;
@ -1115,7 +1120,7 @@ void tst_qqmlengine::singletonInstance()
{
// deleted object
auto dayfly = new QObject{};
auto dayfly = new Dayfly{};
auto id = qmlRegisterSingletonInstance("Vanity", 1, 0, "Dayfly", dayfly);
delete dayfly;
QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: The registered singleton has already been deleted. Ensure that it outlives the engine.");

View File

@ -0,0 +1,4 @@
import QtQuick 2.15
import example.org 1.0
MyClass {test: 42}

View File

@ -0,0 +1,4 @@
import QtQuick 2.15
import example.org 1.0
Child2 {test: test2; test2: 18}

View File

@ -0,0 +1,4 @@
import QtQuick 2.15
import example.org 1.0
Child2 { test: 13 }

View File

@ -0,0 +1,4 @@
import QtQuick 2.15
import example.org 1.0
Child {test: 42}

View File

@ -0,0 +1,4 @@
import QtQuick 2.15
import example.org 1.0
Child {}

View File

@ -0,0 +1,4 @@
import QtQuick 2.15
import example.org 1.0
MyClass {}

View File

@ -1,4 +0,0 @@
import QtQuick 2.13
Item {
default required property int test // cannot have required default property
}

View File

@ -133,6 +133,8 @@ private slots:
void autoComponentCreationInGroupProperty();
void propertyValueSource();
void requiredProperty();
void requiredPropertyFromCpp_data();
void requiredPropertyFromCpp();
void attachedProperties();
void dynamicObjects();
void customVariantTypes();
@ -1673,9 +1675,74 @@ void tst_qqmllanguage::requiredProperty()
QQmlComponent component(&engine, testFileUrl("requiredProperties.2.qml"));
QVERIFY(!component.errors().empty());
}
}
class MyClassWithRequiredProperty : public QObject
{
public:
Q_OBJECT
Q_PROPERTY(int test MEMBER m_test REQUIRED NOTIFY testChanged)
Q_SIGNAL void testChanged();
private:
int m_test;
};
class ChildClassWithoutOwnRequired : public MyClassWithRequiredProperty
{
public:
Q_OBJECT
Q_PROPERTY(int test2 MEMBER m_test2 NOTIFY test2Changed)
Q_SIGNAL void test2Changed();
private:
int m_test2;
};
class ChildClassWithOwnRequired : public MyClassWithRequiredProperty
{
public:
Q_OBJECT
Q_PROPERTY(int test2 MEMBER m_test2 REQUIRED NOTIFY test2Changed)
Q_SIGNAL void test2Changed();
private:
int m_test2;
};
void tst_qqmllanguage::requiredPropertyFromCpp_data()
{
qmlRegisterType<MyClassWithRequiredProperty>("example.org", 1, 0, "MyClass");
qmlRegisterType<ChildClassWithoutOwnRequired>("example.org", 1, 0, "Child");
qmlRegisterType<ChildClassWithOwnRequired>("example.org", 1, 0, "Child2");
QTest::addColumn<QUrl>("setFile");
QTest::addColumn<QUrl>("notSetFile");
QTest::addColumn<QString>("errorMessage");
QTest::addColumn<int>("expectedValue");
QTest::addRow("direct") << testFileUrl("cppRequiredProperty.qml") << testFileUrl("cppRequiredPropertyNotSet.qml") << QString(":4 Required property test was not initialized\n") << 42;
QTest::addRow("in parent") << testFileUrl("cppRequiredPropertyInParent.qml") << testFileUrl("cppRequiredPropertyInParentNotSet.qml") << QString(":4 Required property test was not initialized\n") << 42;
QTest::addRow("in child and parent") << testFileUrl("cppRequiredPropertyInChildAndParent.qml") << testFileUrl("cppRequiredPropertyInChildAndParentNotSet.qml") << QString(":4 Required property test2 was not initialized\n") << 18;
}
void tst_qqmllanguage::requiredPropertyFromCpp()
{
QQmlEngine engine;
QFETCH(QUrl, setFile);
QFETCH(QUrl, notSetFile);
QFETCH(QString, errorMessage);
QFETCH(int, expectedValue);
{
QQmlComponent component(&engine, testFileUrl("requiredProperties.3.qml"));
QVERIFY(!component.errors().empty());
QQmlComponent comp(&engine, notSetFile);
QScopedPointer<QObject> o { comp.create() };
QVERIFY(o.isNull());
QVERIFY(comp.isError());
QCOMPARE(comp.errorString(), notSetFile.toString() + errorMessage);
}
{
QQmlComponent comp(&engine, setFile);
QScopedPointer<QObject> o { comp.create() };
QVERIFY(!o.isNull());
QCOMPARE(o->property("test").toInt(), expectedValue);
}
}

View File

@ -1224,10 +1224,10 @@ void tst_qqmlproperty::read()
}
{
QQmlComponent component(&engine, testFileUrl("readSynthesizedObject.qml"));
QObject *object = component.create();
QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
QQmlProperty p(object, "test", &engine);
QQmlProperty p(object.data(), "test", &engine);
QCOMPARE(p.propertyTypeCategory(), QQmlProperty::Object);
QVERIFY(p.propertyType() != QMetaType::QObjectStar);
@ -1239,10 +1239,10 @@ void tst_qqmlproperty::read()
}
{ // static
QQmlComponent component(&engine, testFileUrl("readSynthesizedObject.qml"));
QObject *object = component.create();
QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
QVariant v = QQmlProperty::read(object, "test", &engine);
QVariant v = QQmlProperty::read(object.data(), "test", &engine);
QCOMPARE(v.userType(), int(QMetaType::QObjectStar));
QCOMPARE(qvariant_cast<QObject *>(v)->property("a").toInt(), 10);
QCOMPARE(qvariant_cast<QObject *>(v)->property("b").toInt(), 19);
@ -1252,41 +1252,38 @@ void tst_qqmlproperty::read()
{
QQmlComponent component(&engine);
component.setData("import Test 1.0\nMyContainer { }", QUrl());
QObject *object = component.create();
QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
QQmlProperty p(object, "MyContainer.foo", qmlContext(object));
QQmlProperty p(object.data(), "MyContainer.foo", qmlContext(object.data()));
QCOMPARE(p.read(), QVariant(13));
delete object;
}
{
QQmlComponent component(&engine);
component.setData("import Test 1.0\nMyContainer { MyContainer.foo: 10 }", QUrl());
QObject *object = component.create();
QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
QQmlProperty p(object, "MyContainer.foo", qmlContext(object));
QQmlProperty p(object.data(), "MyContainer.foo", qmlContext(object.data()));
QCOMPARE(p.read(), QVariant(10));
delete object;
}
{
QQmlComponent component(&engine);
component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
QObject *object = component.create();
QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
QQmlProperty p(object, "Foo.MyContainer.foo", qmlContext(object));
QQmlProperty p(object.data(), "Foo.MyContainer.foo", qmlContext(object.data()));
QCOMPARE(p.read(), QVariant(10));
delete object;
}
{ // static
QQmlComponent component(&engine);
component.setData("import Test 1.0 as Foo\nFoo.MyContainer { Foo.MyContainer.foo: 10 }", QUrl());
QObject *object = component.create();
QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
QCOMPARE(QQmlProperty::read(object, "Foo.MyContainer.foo", qmlContext(object)), QVariant(10));
delete object;
QCOMPARE(QQmlProperty::read(object.data(), "Foo.MyContainer.foo",
qmlContext(object.data())), QVariant(10));
}
}
@ -1447,11 +1444,12 @@ void tst_qqmlproperty::write()
{ // QChar -> QString
QQmlComponent component(&engine);
component.setData("import Test 1.0\nPropertyObject { stringProperty: constQChar }", QUrl());
PropertyObject *obj = qobject_cast<PropertyObject*>(component.create());
QVERIFY(obj != nullptr);
if (obj) {
QQmlProperty stringProperty(obj, "stringProperty");
QCOMPARE(stringProperty.read(), QVariant(QString(obj->constQChar())));
QScopedPointer<QObject> object(component.create());
PropertyObject *propertyObject = qobject_cast<PropertyObject*>(object.data());
QVERIFY(propertyObject != nullptr);
if (propertyObject) {
QQmlProperty stringProperty(propertyObject, "stringProperty");
QCOMPARE(stringProperty.read(), QVariant(QString(propertyObject->constQChar())));
}
}
@ -1628,29 +1626,32 @@ void tst_qqmlproperty::writeObjectToList()
{
QQmlComponent containerComponent(&engine);
containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
QScopedPointer<QObject> object(containerComponent.create());
MyContainer *container = qobject_cast<MyContainer*>(object.data());
QVERIFY(container != nullptr);
QQmlListReference list(container, "children");
QCOMPARE(list.count(), 1);
MyQmlObject *object = new MyQmlObject;
QScopedPointer<MyQmlObject> childObject(new MyQmlObject);
QQmlProperty prop(container, "children");
prop.write(QVariant::fromValue(object));
prop.write(QVariant::fromValue(childObject.data()));
QCOMPARE(list.count(), 1);
QCOMPARE(list.at(0), qobject_cast<QObject*>(object));
QCOMPARE(list.at(0), qobject_cast<QObject*>(childObject.data()));
}
void tst_qqmlproperty::writeListToList()
{
QQmlComponent containerComponent(&engine);
containerComponent.setData("import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl());
MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
QScopedPointer<QObject> object(containerComponent.create());
MyContainer *container = qobject_cast<MyContainer*>(object.data());
QVERIFY(container != nullptr);
QQmlListReference list(container, "children");
QCOMPARE(list.count(), 1);
QList<QObject*> objList;
objList << new MyQmlObject() << new MyQmlObject() << new MyQmlObject() << new MyQmlObject();
objList << new MyQmlObject(this) << new MyQmlObject(this)
<< new MyQmlObject(this) << new MyQmlObject(this);
QQmlProperty prop(container, "children");
prop.write(QVariant::fromValue(objList));
QCOMPARE(list.count(), 4);
@ -1828,10 +1829,11 @@ void tst_qqmlproperty::crashOnValueProperty()
QQmlComponent component(engine);
component.setData("import Test 1.0\nPropertyObject { wrectProperty.x: 10 }", QUrl());
PropertyObject *obj = qobject_cast<PropertyObject*>(component.create());
QVERIFY(obj != nullptr);
QScopedPointer<QObject> object(component.create());
PropertyObject *propertyObject = qobject_cast<PropertyObject*>(object.data());
QVERIFY(propertyObject != nullptr);
QQmlProperty p(obj, "wrectProperty.x", qmlContext(obj));
QQmlProperty p(propertyObject, "wrectProperty.x", qmlContext(propertyObject));
QCOMPARE(p.name(), QString("wrectProperty.x"));
QCOMPARE(p.read(), QVariant(10));

View File

@ -48,6 +48,8 @@
#include <private/qqmlproperty_p.h>
#include <private/qqmlpropertyvalueinterceptor_p.h>
Q_DECLARE_METATYPE(QQmlProperty)
class MyTypeObject : public QObject
{
Q_OBJECT

View File

@ -1,3 +1,5 @@
[tabKey]
opensuse-42.3
opensuse-leap
[enterLeave]
macos

View File

@ -0,0 +1,91 @@
import QtQuick 2.15
import QtQuick.Shapes 1.0
Item {
width: 320
height: 480
Column {
Item {
width: 200
height: 160
Shape {
anchors.fill: parent
vendorExtensionsEnabled: false
ShapePath {
fillColor: "transparent"
strokeColor: "blue"
strokeStyle: ShapePath.DashLine
strokeWidth: 4
PathText {
x: 96
y: 10
font.pixelSize: 120
text: "Qt"
}
}
}
}
Item {
width: 200
height: 160
Rectangle {
anchors.fill: parent
color: "blue"
}
Shape {
anchors.fill: parent
vendorExtensionsEnabled: false
ShapePath {
fillColor: "red"
strokeColor: "blue"
strokeStyle: ShapePath.DashLine
capStyle: ShapePath.RoundCap
strokeWidth: 8
PathText {
x: 96; y: 10
font.pixelSize: 150
text: "Qt"
}
}
}
}
Item {
width: 200
height: 160
Shape {
anchors.fill: parent
vendorExtensionsEnabled: false
ShapePath {
fillGradient: LinearGradient {
x1: 0; x2: 200; y1: 0; y2: 160
spread: ShapeGradient.PadSpread
GradientStop { position: 0.0; color: "red"; }
GradientStop { position: 1.0; color: "green"; }
}
strokeColor: "blue"
strokeStyle: ShapePath.DashLine
joinStyle: ShapePath.RoundJoin
strokeWidth: 4
PathText {
x: 96; y: 10
font.pixelSize: 150
text: "Qt"
}
}
}
}
}
}