aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dist/changes-5.14.189
-rw-r--r--examples/quick/shapes/content/item18.qml2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp5
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp8
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp19
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp15
-rw-r--r--src/qml/jsruntime/qv4object.cpp2
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp2
-rw-r--r--src/qml/jsruntime/qv4promiseobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4proxy.cpp24
-rw-r--r--src/qml/jsruntime/qv4reflect.cpp3
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp35
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp6
-rw-r--r--src/qml/parser/qqmljs.g25
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp8
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp1
-rw-r--r--src/qml/qml/qqmlpropertydata_p.h16
-rw-r--r--src/qmlmodels/qqmladaptormodel.cpp20
-rw-r--r--src/qmlmodels/qqmladaptormodel_p.h9
-rw-r--r--src/qmlmodels/qqmldelegatemodel.cpp12
-rw-r--r--src/qmlmodels/qqmldelegatemodel_p_p.h4
-rw-r--r--src/qmlmodels/qqmllistmodel.cpp8
-rw-r--r--src/qmlmodels/qqmltableinstancemodel.cpp3
-rw-r--r--src/qmlmodels/qqmltableinstancemodel_p.h2
-rw-r--r--src/quick/doc/snippets/qml/xmlrole.xml20
-rw-r--r--src/quick/items/qquickitemview.cpp12
-rw-r--r--src/quick/items/qquicktextinput.cpp12
-rw-r--r--src/quick/items/qquickwindow.cpp5
-rw-r--r--src/quick/items/qquickwindow.h5
-rw-r--r--src/quick/util/qquickpath.cpp4
-rw-r--r--tests/auto/qml/ecmascripttests/BLACKLIST4
-rw-r--r--tests/auto/qml/qqmlcomponent/data/RequiredDefault.qml5
-rw-r--r--tests/auto/qml/qqmlcomponent/data/requiredDefault.1.qml5
-rw-r--r--tests/auto/qml/qqmlcomponent/data/requiredDefault.2.qml3
-rw-r--r--tests/auto/qml/qqmlcomponent/data/requiredDefault.3.qml6
-rw-r--r--tests/auto/qml/qqmlcomponent/data/requiredDefault.4.qml4
-rw-r--r--tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp16
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp7
-rw-r--r--tests/auto/qml/qqmllanguage/data/cppRequiredProperty.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParent.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParentNotSet.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParent.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParentNotSet.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/cppRequiredPropertyNotSet.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp71
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp62
-rw-r--r--tests/auto/qml/qqmlvaluetypes/testtypes.h2
-rw-r--r--tests/auto/quickwidgets/qquickwidget/BLACKLIST2
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_text.qml91
55 files changed, 561 insertions, 141 deletions
diff --git a/dist/changes-5.14.1 b/dist/changes-5.14.1
new file mode 100644
index 0000000000..f4a2ab226a
--- /dev/null
+++ b/dist/changes-5.14.1
@@ -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.
diff --git a/examples/quick/shapes/content/item18.qml b/examples/quick/shapes/content/item18.qml
index 3774d19bc5..192438408d 100644
--- a/examples/quick/shapes/content/item18.qml
+++ b/examples/quick/shapes/content/item18.qml
@@ -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!" }
}
}
}
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index a3d19841cf..d435e82390 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -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) :
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 6c51b4cbcb..df9f117d04 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -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;
}
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index cc89947cec..c2f48ffeac 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -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)
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index dfef52583e..cdb3b8942b 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -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 *)
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index c99cad8e33..78be58c60a 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -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;
+}
}
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index 936c032fad..ce759111f4 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -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();
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index 0cda6b864a..d3ea50867a 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -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);
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 89161433ed..b723141caa 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -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)
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 7d910a1cbc..0c8cc192fc 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -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)
diff --git a/src/qml/jsruntime/qv4promiseobject.cpp b/src/qml/jsruntime/qv4promiseobject.cpp
index 17d218a6eb..ecaff72b22 100644
--- a/src/qml/jsruntime/qv4promiseobject.cpp
+++ b/src/qml/jsruntime/qv4promiseobject.cpp
@@ -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();
diff --git a/src/qml/jsruntime/qv4proxy.cpp b/src/qml/jsruntime/qv4proxy.cpp
index 51f96b9003..24676ffd00 100644
--- a/src/qml/jsruntime/qv4proxy.cpp
+++ b/src/qml/jsruntime/qv4proxy.cpp
@@ -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();
diff --git a/src/qml/jsruntime/qv4reflect.cpp b/src/qml/jsruntime/qv4reflect.cpp
index 0772770d63..2a6c61f044 100644
--- a/src/qml/jsruntime/qv4reflect.cpp
+++ b/src/qml/jsruntime/qv4reflect.cpp
@@ -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)
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index f1375e4ca4..a8a37cda37 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -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());
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index e47a7a0b46..5fc94b9ddd 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -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));
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 9b4a2d575e..209a1b4e76 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -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)
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index 40a434d301..f425c6c87f 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -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);
}
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index 397c0b51a5..2b00caf378 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -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
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 198ce98f2d..a26cdba53a 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -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();
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index c4afbbd598..73b68a763b 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -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;
diff --git a/src/qml/qml/qqmlpropertydata_p.h b/src/qml/qml/qqmlpropertydata_p.h
index 2d9091edcd..7f70c34854 100644
--- a/src/qml/qml/qqmlpropertydata_p.h
+++ b/src/qml/qml/qqmlpropertydata_p.h
@@ -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 &&
diff --git a/src/qmlmodels/qqmladaptormodel.cpp b/src/qmlmodels/qqmladaptormodel.cpp
index fbb85327a7..1f437a08c7 100644
--- a/src/qmlmodels/qqmladaptormodel.cpp
+++ b/src/qmlmodels/qqmladaptormodel.cpp
@@ -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)
diff --git a/src/qmlmodels/qqmladaptormodel_p.h b/src/qmlmodels/qqmladaptormodel_p.h
index a4549127af..ee4862f3b4 100644
--- a/src/qmlmodels/qqmladaptormodel_p.h
+++ b/src/qmlmodels/qqmladaptormodel_p.h
@@ -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; }
diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp
index 3a3903965c..ee407538f1 100644
--- a/src/qmlmodels/qqmldelegatemodel.cpp
+++ b/src/qmlmodels/qqmldelegatemodel.cpp
@@ -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()
diff --git a/src/qmlmodels/qqmldelegatemodel_p_p.h b/src/qmlmodels/qqmldelegatemodel_p_p.h
index a1c4555d01..40c6bcdb21 100644
--- a/src/qmlmodels/qqmldelegatemodel_p_p.h
+++ b/src/qmlmodels/qqmldelegatemodel_p_p.h
@@ -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;
diff --git a/src/qmlmodels/qqmllistmodel.cpp b/src/qmlmodels/qqmllistmodel.cpp
index 2c05b04429..e58fc19178 100644
--- a/src/qmlmodels/qqmllistmodel.cpp
+++ b/src/qmlmodels/qqmllistmodel.cpp
@@ -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();
diff --git a/src/qmlmodels/qqmltableinstancemodel.cpp b/src/qmlmodels/qqmltableinstancemodel.cpp
index b4d1e61e31..29c307a47a 100644
--- a/src/qmlmodels/qqmltableinstancemodel.cpp
+++ b/src/qmlmodels/qqmltableinstancemodel.cpp
@@ -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)
{
}
diff --git a/src/qmlmodels/qqmltableinstancemodel_p.h b/src/qmlmodels/qqmltableinstancemodel_p.h
index d924455918..661ea3a3aa 100644
--- a/src/qmlmodels/qqmltableinstancemodel_p.h
+++ b/src/qmlmodels/qqmltableinstancemodel_p.h
@@ -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;
diff --git a/src/quick/doc/snippets/qml/xmlrole.xml b/src/quick/doc/snippets/qml/xmlrole.xml
deleted file mode 100644
index 70280e067d..0000000000
--- a/src/quick/doc/snippets/qml/xmlrole.xml
+++ /dev/null
@@ -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>
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 0d30606ef7..7fb392233e 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -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();
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index 1f6f24e419..b204cb3417 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -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
{
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 2eee98a738..3bb6c19dce 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -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
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index 56d50cec2a..d22bba4512 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -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,
diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp
index 375d0265e8..74ee52b1d3 100644
--- a/src/quick/util/qquickpath.cpp
+++ b/src/quick/util/qquickpath.cpp
@@ -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)
diff --git a/tests/auto/qml/ecmascripttests/BLACKLIST b/tests/auto/qml/ecmascripttests/BLACKLIST
deleted file mode 100644
index 1ed255e9e2..0000000000
--- a/tests/auto/qml/ecmascripttests/BLACKLIST
+++ /dev/null
@@ -1,4 +0,0 @@
-[runInterpreted]
-macos ci
-[runJitted]
-macos
diff --git a/tests/auto/qml/qqmlcomponent/data/RequiredDefault.qml b/tests/auto/qml/qqmlcomponent/data/RequiredDefault.qml
new file mode 100644
index 0000000000..7e8f225a52
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/RequiredDefault.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+Item {
+ required default property Text requiredDefault
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/requiredDefault.1.qml b/tests/auto/qml/qqmlcomponent/data/requiredDefault.1.qml
new file mode 100644
index 0000000000..68dff22f33
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/requiredDefault.1.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+RequiredDefault {
+ Text {text: "Hello, world!"}
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/requiredDefault.2.qml b/tests/auto/qml/qqmlcomponent/data/requiredDefault.2.qml
new file mode 100644
index 0000000000..a6c4e8ea3f
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/requiredDefault.2.qml
@@ -0,0 +1,3 @@
+import QtQuick 2.15
+
+RequiredDefault { }
diff --git a/tests/auto/qml/qqmlcomponent/data/requiredDefault.3.qml b/tests/auto/qml/qqmlcomponent/data/requiredDefault.3.qml
new file mode 100644
index 0000000000..19b3271858
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/requiredDefault.3.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.15
+import qt.test 1.0
+
+RequiredDefaultCpp {
+ Text {text: "Hello, world!"}
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/requiredDefault.4.qml b/tests/auto/qml/qqmlcomponent/data/requiredDefault.4.qml
new file mode 100644
index 0000000000..acd56db328
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/requiredDefault.4.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.15
+import qt.test 1.0
+
+RequiredDefaultCpp { }
diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
index 2acc62ca28..43cbd93396 100644
--- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
+++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
@@ -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";
}
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index ab4c083b65..cfbbd2a94c 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -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.");
diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredProperty.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredProperty.qml
new file mode 100644
index 0000000000..76673f6409
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cppRequiredProperty.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.15
+import example.org 1.0
+
+MyClass {test: 42}
diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParent.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParent.qml
new file mode 100644
index 0000000000..d4c059581c
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParent.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.15
+import example.org 1.0
+
+Child2 {test: test2; test2: 18}
diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParentNotSet.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParentNotSet.qml
new file mode 100644
index 0000000000..082e22dc3f
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParentNotSet.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.15
+import example.org 1.0
+
+Child2 { test: 13 }
diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParent.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParent.qml
new file mode 100644
index 0000000000..6602684542
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParent.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.15
+import example.org 1.0
+
+Child {test: 42}
diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParentNotSet.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParentNotSet.qml
new file mode 100644
index 0000000000..5971b0c263
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParentNotSet.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.15
+import example.org 1.0
+
+Child {}
diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyNotSet.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyNotSet.qml
new file mode 100644
index 0000000000..dab48a3d71
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyNotSet.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.15
+import example.org 1.0
+
+MyClass {}
diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml
deleted file mode 100644
index 534322215f..0000000000
--- a/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml
+++ /dev/null
@@ -1,4 +0,0 @@
-import QtQuick 2.13
-Item {
- default required property int test // cannot have required default property
-}
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 4d2f773dbf..5027c0825f 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -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);
}
}
diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index f039ccc110..83e173f379 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -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));
diff --git a/tests/auto/qml/qqmlvaluetypes/testtypes.h b/tests/auto/qml/qqmlvaluetypes/testtypes.h
index e11d831236..78797f06b1 100644
--- a/tests/auto/qml/qqmlvaluetypes/testtypes.h
+++ b/tests/auto/qml/qqmlvaluetypes/testtypes.h
@@ -48,6 +48,8 @@
#include <private/qqmlproperty_p.h>
#include <private/qqmlpropertyvalueinterceptor_p.h>
+Q_DECLARE_METATYPE(QQmlProperty)
+
class MyTypeObject : public QObject
{
Q_OBJECT
diff --git a/tests/auto/quickwidgets/qquickwidget/BLACKLIST b/tests/auto/quickwidgets/qquickwidget/BLACKLIST
index 18ea65bb72..095e9ee484 100644
--- a/tests/auto/quickwidgets/qquickwidget/BLACKLIST
+++ b/tests/auto/quickwidgets/qquickwidget/BLACKLIST
@@ -1,3 +1,5 @@
[tabKey]
opensuse-42.3
opensuse-leap
+[enterLeave]
+macos
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_text.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_text.qml
new file mode 100644
index 0000000000..37367054b5
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_text.qml
@@ -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"
+ }
+ }
+ }
+ }
+ }
+}