Merge remote-tracking branch 'origin/5.15' into dev
Change-Id: I1e1d9585d876a8eacd4c24afc894a33075f51a13
This commit is contained in:
commit
5be153af99
|
@ -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.
|
|
@ -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!" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) :
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 *)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[runInterpreted]
|
||||
macos ci
|
||||
[runJitted]
|
||||
macos
|
|
@ -0,0 +1,5 @@
|
|||
import QtQuick 2.15
|
||||
|
||||
Item {
|
||||
required default property Text requiredDefault
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
import QtQuick 2.15
|
||||
|
||||
RequiredDefault {
|
||||
Text {text: "Hello, world!"}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
import QtQuick 2.15
|
||||
|
||||
RequiredDefault { }
|
|
@ -0,0 +1,6 @@
|
|||
import QtQuick 2.15
|
||||
import qt.test 1.0
|
||||
|
||||
RequiredDefaultCpp {
|
||||
Text {text: "Hello, world!"}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
import QtQuick 2.15
|
||||
import qt.test 1.0
|
||||
|
||||
RequiredDefaultCpp { }
|
|
@ -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";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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.");
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
import QtQuick 2.15
|
||||
import example.org 1.0
|
||||
|
||||
MyClass {test: 42}
|
|
@ -0,0 +1,4 @@
|
|||
import QtQuick 2.15
|
||||
import example.org 1.0
|
||||
|
||||
Child2 {test: test2; test2: 18}
|
|
@ -0,0 +1,4 @@
|
|||
import QtQuick 2.15
|
||||
import example.org 1.0
|
||||
|
||||
Child2 { test: 13 }
|
|
@ -0,0 +1,4 @@
|
|||
import QtQuick 2.15
|
||||
import example.org 1.0
|
||||
|
||||
Child {test: 42}
|
|
@ -0,0 +1,4 @@
|
|||
import QtQuick 2.15
|
||||
import example.org 1.0
|
||||
|
||||
Child {}
|
|
@ -0,0 +1,4 @@
|
|||
import QtQuick 2.15
|
||||
import example.org 1.0
|
||||
|
||||
MyClass {}
|
|
@ -1,4 +0,0 @@
|
|||
import QtQuick 2.13
|
||||
Item {
|
||||
default required property int test // cannot have required default property
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
#include <private/qqmlproperty_p.h>
|
||||
#include <private/qqmlpropertyvalueinterceptor_p.h>
|
||||
|
||||
Q_DECLARE_METATYPE(QQmlProperty)
|
||||
|
||||
class MyTypeObject : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
[tabKey]
|
||||
opensuse-42.3
|
||||
opensuse-leap
|
||||
[enterLeave]
|
||||
macos
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue