aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2020-01-09 01:00:43 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2020-01-09 07:24:26 +0000
commitba10b0b9ed93be007fcb156710ef6081000e3ae3 (patch)
treeea17c625900b83d5955cb4a2db1587a5f07e2fb4 /src
parent653c25d48298fb747cf6f3b012816855c51d4260 (diff)
parent1798d20ded699837f7b3afe0bb340617af266518 (diff)
Merge remote-tracking branch 'origin/5.14' into 5.15
Conflicts: src/particles/qquickitemparticle.cpp src/qmlmodels/qqmladaptormodel.cpp tests/auto/particles/qquickitemparticle/tst_qquickitemparticle.cpp Change-Id: Ibd8fbb91da6893a09f4ffe61ad0b95d8149bbc87
Diffstat (limited to 'src')
-rw-r--r--src/particles/qquickitemparticle.cpp84
-rw-r--r--src/particles/qquickitemparticle_p.h3
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp8
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp3
-rw-r--r--src/qml/jsruntime/qv4engine.cpp99
-rw-r--r--src/qml/jsruntime/qv4engine_p.h11
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp8
-rw-r--r--src/qml/jsruntime/qv4object_p.h2
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp2
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp1
-rw-r--r--src/qml/jsruntime/qv4proxy.cpp2
-rw-r--r--src/qml/jsruntime/qv4regexp.cpp3
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp7
-rw-r--r--src/qml/jsruntime/qv4value_p.h2
-rw-r--r--src/qml/memory/qv4mm.cpp2
-rw-r--r--src/qml/qml/qqmlapplicationengine.cpp2
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp2
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp13
-rw-r--r--src/qmlmodels/qqmladaptormodel.cpp76
-rw-r--r--src/qmlworkerscript/qquickworkerscript.cpp11
-rw-r--r--src/quick/configure.json2
-rw-r--r--src/quick/items/qquickitem_p.h2
-rw-r--r--src/quick/scenegraph/qsgrhitextureglyphcache.cpp2
24 files changed, 247 insertions, 104 deletions
diff --git a/src/particles/qquickitemparticle.cpp b/src/particles/qquickitemparticle.cpp
index 740d0f60f3..ce254c212d 100644
--- a/src/particles/qquickitemparticle.cpp
+++ b/src/particles/qquickitemparticle.cpp
@@ -136,6 +136,7 @@ QQuickItemParticle::QQuickItemParticle(QQuickItem *parent) :
QQuickItemParticle::~QQuickItemParticle()
{
delete clock;
+ qDeleteAll(m_managed);
}
void QQuickItemParticle::freeze(QQuickItem* item)
@@ -172,7 +173,8 @@ void QQuickItemParticle::give(QQuickItem *item)
void QQuickItemParticle::initialize(int gIdx, int pIdx)
{
- m_loadables << m_system->groupData[gIdx]->data[pIdx];//defer to other thread
+ Q_UNUSED(gIdx);
+ Q_UNUSED(pIdx);
}
void QQuickItemParticle::commit(int, int)
@@ -205,50 +207,43 @@ void QQuickItemParticle::tick(int time)
{
Q_UNUSED(time);//only needed because QTickAnimationProxy expects one
processDeletables();
-
- foreach (QQuickParticleData* d, m_loadables){
- Q_ASSERT(d);
- if (m_stasis.contains(d->delegate))
- qWarning() << "Current model particles prefers overwrite:false";
- //remove old item from the particle that is dying to make room for this one
- if (d->delegate) {
- m_deletables << d->delegate;
- d->delegate = nullptr;
- }
- QQuickItem* parentItem = nullptr;
- if (!m_pendingItems.isEmpty()){
- QQuickItem *item = m_pendingItems.front();
- m_pendingItems.pop_front();
- parentItem = item->parentItem();
- d->delegate = item;
- }else if (m_delegate){
- d->delegate = qobject_cast<QQuickItem*>(m_delegate->create(qmlContext(this)));
- if (d->delegate)
- m_managed << d->delegate;
- }
- if (d && d->delegate){//###Data can be zero if creating an item leads to a reset - this screws things up.
- d->delegate->setX(d->curX(m_system) - d->delegate->width() / 2); //TODO: adjust for system?
- d->delegate->setY(d->curY(m_system) - d->delegate->height() / 2);
- QQuickItemParticleAttached* mpa = qobject_cast<QQuickItemParticleAttached*>(qmlAttachedPropertiesObject<QQuickItemParticle>(d->delegate));
- if (mpa){
- mpa->m_parentItem = parentItem;
- mpa->m_mp = this;
- mpa->attach();
+ for (auto groupId : groupIds()) {
+ for (QQuickParticleData* d : qAsConst(m_system->groupData[groupId]->data)) {
+ if (!d->delegate && d->t != -1 && d->stillAlive(m_system)) {
+ QQuickItem* parentItem = nullptr;
+ if (!m_pendingItems.isEmpty()){
+ QQuickItem *item = m_pendingItems.front();
+ m_pendingItems.pop_front();
+ parentItem = item->parentItem();
+ d->delegate = item;
+ }else if (m_delegate){
+ d->delegate = qobject_cast<QQuickItem*>(m_delegate->create(qmlContext(this)));
+ if (d->delegate)
+ m_managed << d->delegate;
+ }
+ if (d && d->delegate){//###Data can be zero if creating an item leads to a reset - this screws things up.
+ d->delegate->setX(d->curX(m_system) - d->delegate->width() / 2); //TODO: adjust for system?
+ d->delegate->setY(d->curY(m_system) - d->delegate->height() / 2);
+ QQuickItemParticleAttached* mpa = qobject_cast<QQuickItemParticleAttached*>(qmlAttachedPropertiesObject<QQuickItemParticle>(d->delegate));
+ if (mpa){
+ mpa->m_parentItem = parentItem;
+ mpa->m_mp = this;
+ mpa->attach();
+ }
+ d->delegate->setParentItem(this);
+ if (m_fade)
+ d->delegate->setOpacity(0.);
+ d->delegate->setVisible(false);//Will be set to true when we prepare the next frame
+ m_activeCount++;
+ }
}
- d->delegate->setParentItem(this);
- if (m_fade)
- d->delegate->setOpacity(0.);
- d->delegate->setVisible(false);//Will be set to true when we prepare the next frame
- m_activeCount++;
}
}
- m_loadables.clear();
}
void QQuickItemParticle::reset()
{
QQuickParticlePainter::reset();
- m_loadables.clear();
// delete all managed items which had their logical particles cleared
// but leave it alone if the logical particle is maintained
@@ -258,7 +253,7 @@ void QQuickItemParticle::reset()
lost.remove(d->delegate);
}
}
- m_deletables.append(lost.values());
+ m_deletables.unite(lost);
//TODO: This doesn't yet handle calling detach on taken particles in the system reset case
processDeletables();
}
@@ -267,18 +262,9 @@ void QQuickItemParticle::reset()
QSGNode* QQuickItemParticle::updatePaintNode(QSGNode* n, UpdatePaintNodeData* d)
{
//Dummy update just to get painting tick
- if (m_pleaseReset){
+ if (m_pleaseReset)
m_pleaseReset = false;
- //Refill loadables, delayed here so as to only happen once per frame max
- //### Constant resetting might lead to m_loadables never being populated when tick() occurs
- for (auto groupId : groupIds()) {
- for (QQuickParticleData* d : qAsConst(m_system->groupData[groupId]->data)) {
- if (!d->delegate && d->t != -1 && d->stillAlive(m_system)) {
- m_loadables << d;
- }
- }
- }
- }
+
prepareNextFrame();
update();//Get called again
diff --git a/src/particles/qquickitemparticle_p.h b/src/particles/qquickitemparticle_p.h
index ea46c67db7..32c9881691 100644
--- a/src/particles/qquickitemparticle_p.h
+++ b/src/particles/qquickitemparticle_p.h
@@ -108,9 +108,8 @@ protected:
private:
void processDeletables();
void tick(int time = 0);
- QList<QQuickItem* > m_deletables;
+ QSet<QQuickItem* > m_deletables;
QList<QQuickItem* > m_managed;
- QList< QQuickParticleData* > m_loadables;
bool m_fade;
QList<QQuickItem*> m_pendingItems;
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index 654d33b8d1..1c587d2367 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -586,7 +586,7 @@ uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n)
obj->arrayPut(oldSize, os->values.data() + os->offset, chunk);
toCopy -= chunk;
if (toCopy)
- obj->arrayPut(oldSize + chunk, os->values.data(), toCopy);
+ obj->setArrayLength(oldSize + chunk + toCopy);
}
return oldSize + n;
@@ -659,6 +659,12 @@ bool ArrayElementLessThan::operator()(Value v1, Value v2) const
}
ScopedString p1s(scope, v1.toString(scope.engine));
ScopedString p2s(scope, v2.toString(scope.engine));
+
+ if (!p1s)
+ return false;
+ if (!p2s)
+ return true;
+
return p1s->toQString() < p2s->toQString();
}
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index d8d0d4739f..6c51b4cbcb 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -1048,8 +1048,9 @@ ReturnedValue ArrayPrototype::method_includes(const FunctionObject *b, const Val
}
}
+ ScopedValue val(scope);
while (k < len) {
- ScopedValue val(scope, instance->get(k));
+ val = instance->get(k);
if (val->sameValueZero(argv[0])) {
return Encode(true);
}
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index cd2327a45e..14eaa5bce8 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -43,6 +43,7 @@
#include <private/qqmljsdiagnosticmessage_p.h>
#include <QtCore/QTextStream>
+#include <QtCore/private/qvariant_p.h>
#include <QDateTime>
#include <QDir>
#include <QFileInfo>
@@ -118,6 +119,7 @@
#endif
#include <private/qv4sqlerrors_p.h>
#include <qqmlfile.h>
+#include <qmetatype.h>
#if USE(PTHREADS)
# include <pthread.h>
@@ -185,6 +187,91 @@ static void restoreJSValue(QDataStream &stream, void *data)
}
}
+struct JSArrayIterator {
+ QJSValue const* data;
+ quint32 index;
+};
+
+namespace {
+void createNewIteratorIfNonExisting(void **iterator) {
+ if (*iterator == nullptr)
+ *iterator = new JSArrayIterator;
+}
+}
+
+static QtMetaTypePrivate::QSequentialIterableImpl jsvalueToSequence (const QJSValue& value) {
+ using namespace QtMetaTypePrivate;
+
+ QSequentialIterableImpl iterator {};
+ if (!value.isArray()) {
+ // set up some functions so that non-array QSequentialIterables do not crash
+ // but instead appear as an empty sequence
+ iterator._size = [](const void *) {return 0;};
+ iterator._moveToBegin = [](const void *, void **) {};
+ iterator._moveToEnd = [](const void *, void **) {};
+ iterator._advance = [](void **, int) {};
+ iterator._equalIter = [](void * const *, void * const *){return true; /*all iterators are nullptr*/};
+ iterator._destroyIter = [](void **){};
+ return iterator;
+ }
+
+ iterator._iterable = &value;
+ iterator._iterator = nullptr;
+ iterator._metaType_id = qMetaTypeId<QVariant>();
+ iterator._metaType_flags = QVariantConstructionFlags::ShouldDeleteVariantData;
+ iterator._iteratorCapabilities = RandomAccessCapability | BiDirectionalCapability | ForwardCapability;
+ iterator._size = [](const void *p) -> int {
+ return static_cast<QJSValue const *>(p)->property(QString::fromLatin1("length")).toInt();
+ };
+ /* Lifetime management notes:
+ * _at and _get return a pointer to a JSValue allocated via QMetaType::create
+ * Because we set QVariantConstructionFlags::ShouldDeleteVariantData, QSequentialIterable::at
+ * and QSequentialIterable::operator*() will free that memory
+ */
+
+ iterator._at = [](const void *iterable, int index) -> void const * {
+ auto const value = static_cast<QJSValue const *>(iterable)->property(quint32(index)).toVariant();
+ return QMetaType::create(qMetaTypeId<QVariant>(), &value);
+ };
+ iterator._moveToBegin = [](const void *iterable, void **iterator) {
+ createNewIteratorIfNonExisting(iterator);
+ auto jsArrayIterator = static_cast<JSArrayIterator *>(*iterator);
+ jsArrayIterator->index = 0;
+ jsArrayIterator->data = reinterpret_cast<QJSValue const*>(iterable);
+ };
+ iterator._moveToEnd = [](const void *iterable, void **iterator) {
+ createNewIteratorIfNonExisting(iterator);
+ auto jsArrayIterator = static_cast<JSArrayIterator *>(*iterator);
+ auto length = static_cast<QJSValue const *>(iterable)->property(QString::fromLatin1("length")).toInt();
+ jsArrayIterator->data = reinterpret_cast<QJSValue const*>(iterable);
+ jsArrayIterator->index = quint32(length);
+ };
+ iterator._advance = [](void **iterator, int advanceBy) {
+ static_cast<JSArrayIterator *>(*iterator)->index += quint32(advanceBy);
+ };
+ iterator._get = []( void * const *iterator, int metaTypeId, uint flags) -> VariantData {
+ auto const * const arrayIterator = static_cast<const JSArrayIterator *>(*iterator);
+ QJSValue const * const jsArray = arrayIterator->data;
+ auto const value = jsArray->property(arrayIterator->index).toVariant();
+ Q_ASSERT(flags & QVariantConstructionFlags::ShouldDeleteVariantData);
+ return {metaTypeId, QMetaType::create(qMetaTypeId<QVariant>(), &value), flags};
+ };
+ iterator._destroyIter = [](void **iterator) {
+ delete static_cast<JSArrayIterator *>(*iterator);
+ };
+ iterator._equalIter = [](void * const *p, void * const *other) {
+ auto this_ = static_cast<const JSArrayIterator *>(*p);
+ auto that_ = static_cast<const JSArrayIterator *>(*other);
+ return this_->index == that_->index && this_->data == that_->data;
+ };
+ iterator._copyIter = [](void **iterator, void * const * otherIterator) {
+ auto *otherIter = (static_cast<JSArrayIterator const *>(*otherIterator));
+ static_cast<JSArrayIterator *>(*iterator)->index = otherIter->index;
+ static_cast<JSArrayIterator *>(*iterator)->data = otherIter->data;
+ };
+ return iterator;
+}
+
ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
: executableAllocator(new QV4::ExecutableAllocator)
, regExpAllocator(new QV4::ExecutableAllocator)
@@ -712,6 +799,8 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
QMetaType::registerConverter<QJSValue, QVariantList>(convertJSValueToVariantType<QVariantList>);
if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QStringList>())
QMetaType::registerConverter<QJSValue, QStringList>(convertJSValueToVariantType<QStringList>);
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QtMetaTypePrivate::QSequentialIterableImpl>())
+ QMetaType::registerConverter<QJSValue, QtMetaTypePrivate::QSequentialIterableImpl>(jsvalueToSequence);
QMetaType::registerStreamOperators(qMetaTypeId<QJSValue>(), saveJSValue, restoreJSValue);
QV4::QObjectWrapper::initializeBindings(this);
@@ -1178,8 +1267,11 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file)
void ExecutionEngine::markObjects(MarkStack *markStack)
{
for (int i = 0; i < NClasses; ++i)
- if (classes[i])
+ if (classes[i]) {
classes[i]->mark(markStack);
+ if (markStack->top >= markStack->limit)
+ markStack->drain();
+ }
markStack->drain();
identifierTable->markObjects(markStack);
@@ -2238,4 +2330,9 @@ int ExecutionEngine::registerExtension()
return registrationData()->extensionCount++;
}
+QNetworkAccessManager *QV4::detail::getNetworkAccessManager(ExecutionEngine *engine)
+{
+ return engine->qmlEngine()->networkAccessManager();
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index d233347060..e0025feb00 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -91,7 +91,14 @@ class PageAllocation;
QT_BEGIN_NAMESPACE
-namespace QV4 { struct QObjectMethod; }
+class QNetworkAccessManager;
+
+namespace QV4 {
+struct QObjectMethod;
+namespace detail {
+QNetworkAccessManager *getNetworkAccessManager(ExecutionEngine *engine);
+}
+}
// Used to allow a QObject method take and return raw V4 handles without having to expose
// 48 in the public API.
@@ -348,6 +355,8 @@ public:
FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); }
FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); }
+ QNetworkAccessManager* (*networkAccessManager)(ExecutionEngine*) = detail::getNetworkAccessManager;
+
enum JSStrings {
String_Empty,
String_undefined,
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 6fb7946023..dfef52583e 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -364,7 +364,13 @@ ReturnedValue FunctionPrototype::method_apply(const QV4::FunctionObject *b, cons
if (!arr)
return v4->throwTypeError();
- uint len = arr->getLength();
+ const qint64 len64 = arr->getLength();
+ if (len64 < 0ll || len64 > qint64(std::numeric_limits<int>::max()))
+ return v4->throwRangeError(QStringLiteral("Invalid array length."));
+ if (len64 > qint64(v4->jsStackLimit - v4->jsStackTop))
+ return v4->throwRangeError(QStringLiteral("Array too large for apply()."));
+
+ const uint len = uint(len64);
Scope scope(v4);
Value *arguments = scope.alloc<Scope::Uninitialized>(len);
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index f3375929a3..9e901d6a34 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -157,7 +157,7 @@ struct Q_QML_EXPORT Object: Managed {
const Value *propertyData(uint index) const { return d()->propertyData(index); }
Heap::ArrayData *arrayData() const { return d()->arrayData; }
- void setArrayData(ArrayData *a) { d()->arrayData.set(engine(), a->d()); }
+ void setArrayData(ArrayData *a) { d()->arrayData.set(engine(), a ? a->d() : nullptr); }
void getProperty(const InternalClassEntry &entry, Property *p) const;
void setProperty(const InternalClassEntry &entry, const Property *p);
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index e529b8e86b..65f6fa8b12 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -182,7 +182,7 @@ PropertyKey ForInIteratorObject::nextProperty() const
if (d()->current != d()->object) {
o = d()->object;
bool shadowed = false;
- while (o->d() != c->heapObject()) {
+ while (o && o->d() != c->heapObject()) {
if (o->getOwnProperty(key) != Attr_Invalid) {
shadowed = true;
break;
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 3d3b3f413f..7d910a1cbc 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -658,6 +658,7 @@ ReturnedValue ObjectPrototype::method_toString(const FunctionObject *b, const Va
ReturnedValue ObjectPrototype::method_toLocaleString(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(b);
+ CHECK_STACK_LIMITS(scope.engine)
ScopedObject o(scope, thisObject->toObject(scope.engine));
if (!o)
RETURN_UNDEFINED();
diff --git a/src/qml/jsruntime/qv4proxy.cpp b/src/qml/jsruntime/qv4proxy.cpp
index 9325e2e53b..51f96b9003 100644
--- a/src/qml/jsruntime/qv4proxy.cpp
+++ b/src/qml/jsruntime/qv4proxy.cpp
@@ -515,7 +515,7 @@ ProxyObjectOwnPropertyKeyIterator::ProxyObjectOwnPropertyKeyIterator(ArrayObject
PropertyKey ProxyObjectOwnPropertyKeyIterator::next(const Object *m, Property *pd, PropertyAttributes *attrs)
{
- if (index >= len)
+ if (index >= len || m == nullptr)
return PropertyKey::invalid();
Scope scope(m);
diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp
index 4ed1dbd5aa..76daead842 100644
--- a/src/qml/jsruntime/qv4regexp.cpp
+++ b/src/qml/jsruntime/qv4regexp.cpp
@@ -73,14 +73,13 @@ DEFINE_MANAGED_VTABLE(RegExp);
uint RegExp::match(const QString &string, int start, uint *matchOffsets)
{
- static const uint offsetJITFail = std::numeric_limits<unsigned>::max() - 1;
-
if (!isValid())
return JSC::Yarr::offsetNoMatch;
WTF::String s(string);
#if ENABLE(YARR_JIT)
+ static const uint offsetJITFail = std::numeric_limits<unsigned>::max() - 1;
auto *priv = d();
if (priv->hasValidJITCode()) {
uint ret = JSC::Yarr::offsetNoMatch;
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index c1a42c4afa..f1375e4ca4 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -961,8 +961,8 @@ ReturnedValue RegExpPrototype::method_compile(const FunctionObject *b, const Val
return scope.engine->throwTypeError();
Scoped<RegExpObject> re(scope, scope.engine->regExpCtor()->callAsConstructor(argv, argc));
-
- r->d()->value.set(scope.engine, re->value());
+ if (re) // Otherwise the regexp constructor should have thrown an exception
+ r->d()->value.set(scope.engine, re->value());
return Encode::undefined();
}
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index 9c50ac2b95..2ed1971235 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -1409,7 +1409,8 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_set(const FunctionObject *b,
if (scope.engine->hasException || l != len)
return scope.engine->throwTypeError();
- if (offset + l > a->length())
+ const uint aLength = a->length();
+ if (offset > aLength || l > aLength - offset)
RETURN_RESULT(scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range")));
uint idx = 0;
@@ -1439,7 +1440,9 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_set(const FunctionObject *b,
return scope.engine->throwTypeError();
uint l = srcTypedArray->length();
- if (offset + l > a->length())
+
+ const uint aLength = a->length();
+ if (offset > aLength || l > aLength - offset)
RETURN_RESULT(scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range")));
char *dest = buffer->d()->data->data() + a->d()->byteOffset + offset*elementSize;
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 4e901721cb..ae12033eb4 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -555,6 +555,8 @@ struct ValueArray {
} else {
while (v < end) {
v->mark(markStack);
+ if (markStack->top >= markStack->limit)
+ markStack->drain();
++v;
}
}
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 3465036c86..35b2ff2749 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -1220,6 +1220,8 @@ void MemoryManager::collectFromJSStack(MarkStack *markStack) const
Q_ASSERT(m->inUse());
// Skip pointers to already freed objects, they are bogus as well
m->mark(markStack);
+ if (markStack->top >= markStack->limit)
+ markStack->drain();
}
++v;
}
diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp
index adb036e2d0..7f80fe5e1c 100644
--- a/src/qml/qml/qqmlapplicationengine.cpp
+++ b/src/qml/qml/qqmlapplicationengine.cpp
@@ -127,7 +127,7 @@ void QQmlApplicationEnginePrivate::finishLoad(QQmlComponent *c)
switch (c->status()) {
case QQmlComponent::Error:
qWarning() << "QQmlApplicationEngine failed to load component";
- qWarning() << qPrintable(c->errorString());
+ warning(c->errors());
q->objectCreated(nullptr, c->url());
break;
case QQmlComponent::Ready: {
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index df4639bb1d..c2e7be73e7 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -1651,7 +1651,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
Scope scope(f->engine());
const QQmlXMLHttpRequestCtor *ctor = static_cast<const QQmlXMLHttpRequestCtor *>(f);
- QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->qmlEngine()->networkAccessManager(), scope.engine);
+ QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->networkAccessManager(scope.engine), scope.engine);
Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocate<QQmlXMLHttpRequestWrapper>(r));
ScopedObject proto(scope, ctor->d()->proto);
w->setPrototypeUnchecked(proto);
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index d634a48443..f5e723419e 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -1553,11 +1553,12 @@ static QString jsStack(QV4::ExecutionEngine *engine) {
return stack;
}
-static QString serializeArray(Object *array, ExecutionEngine *v4) {
+static QString serializeArray(Object *array, ExecutionEngine *v4, QSet<QV4::Heap::Object *> &alreadySeen) {
Scope scope(v4);
ScopedValue val(scope);
QString result;
+ alreadySeen.insert(array->d());
result += QLatin1Char('[');
const uint length = array->getLength();
for (uint i = 0; i < length; ++i) {
@@ -1565,12 +1566,15 @@ static QString serializeArray(Object *array, ExecutionEngine *v4) {
result += QLatin1Char(',');
val = array->get(i);
if (val->isManaged() && val->managed()->isArrayLike())
- result += serializeArray(val->objectValue(), v4);
+ if (!alreadySeen.contains(val->objectValue()->d()))
+ result += serializeArray(val->objectValue(), v4, alreadySeen);
+ else
+ result += QLatin1String("[Circular]");
else
result += val->toQStringNoThrow();
}
result += QLatin1Char(']');
-
+ alreadySeen.remove(array->d());
return result;
};
@@ -1600,8 +1604,9 @@ static ReturnedValue writeToConsole(const FunctionObject *b, const Value *, cons
if (i != start)
result.append(QLatin1Char(' '));
+ QSet<QV4::Heap::Object *> alreadySeenElements;
if (argv[i].isManaged() && argv[i].managed()->isArrayLike())
- result.append(serializeArray(argv[i].objectValue(), v4));
+ result.append(serializeArray(argv[i].objectValue(), v4, alreadySeenElements));
else
result.append(argv[i].toQStringNoThrow());
}
diff --git a/src/qmlmodels/qqmladaptormodel.cpp b/src/qmlmodels/qqmladaptormodel.cpp
index 012540244f..cf0d8fbb2f 100644
--- a/src/qmlmodels/qqmladaptormodel.cpp
+++ b/src/qmlmodels/qqmladaptormodel.cpp
@@ -199,12 +199,11 @@ public:
RETURN_RESULT(scope.engine->throwTypeError(QStringLiteral("Not a valid DelegateModel object")));
const QQmlAdaptorModel *const model = static_cast<QQmlDMCachedModelData *>(o->d()->item)->type->model;
- if (o->d()->item->index >= 0 && *model) {
- const QAbstractItemModel * const aim = model->aim();
- RETURN_RESULT(QV4::Encode(aim->hasChildren(aim->index(o->d()->item->index, 0, model->rootIndex))));
- } else {
- RETURN_RESULT(QV4::Encode(false));
+ if (o->d()->item->index >= 0) {
+ if (const QAbstractItemModel *const aim = model->aim())
+ RETURN_RESULT(QV4::Encode(aim->hasChildren(aim->index(o->d()->item->index, 0, model->rootIndex))));
}
+ RETURN_RESULT(QV4::Encode(false));
}
@@ -400,23 +399,24 @@ public:
bool hasModelChildren() const
{
- if (index >= 0 && *type->model) {
- const QAbstractItemModel * const model = type->model->aim();
- return model->hasChildren(model->index(row, column, type->model->rootIndex));
- } else {
- return false;
+ if (index >= 0) {
+ if (const QAbstractItemModel *const model = type->model->aim())
+ return model->hasChildren(model->index(row, column, type->model->rootIndex));
}
+ return false;
}
QVariant value(int role) const override
{
- return type->model->aim()->index(row, column, type->model->rootIndex).data(role);
+ if (const QAbstractItemModel *aim = type->model->aim())
+ return aim->index(row, column, type->model->rootIndex).data(role);
+ return QVariant();
}
void setValue(int role, const QVariant &value) override
{
- type->model->aim()->setData(
- type->model->aim()->index(row, column, type->model->rootIndex), value, role);
+ if (QAbstractItemModel *aim = type->model->aim())
+ aim->setData(aim->index(row, column, type->model->rootIndex), value, role);
}
QV4::ReturnedValue get() override
@@ -444,12 +444,16 @@ public:
int rowCount(const QQmlAdaptorModel &model) const override
{
- return model.aim()->rowCount(model.rootIndex);
+ if (const QAbstractItemModel *aim = model.aim())
+ return aim->rowCount(model.rootIndex);
+ return 0;
}
int columnCount(const QQmlAdaptorModel &model) const override
{
- return model.aim()->columnCount(model.rootIndex);
+ if (const QAbstractItemModel *aim = model.aim())
+ return aim->columnCount(model.rootIndex);
+ return 0;
}
void cleanup(QQmlAdaptorModel &) const override
@@ -464,39 +468,46 @@ public:
dataType->initializeMetaType(model);
}
- QHash<QByteArray, int>::const_iterator it = roleNames.find(role.toUtf8());
- if (it != roleNames.end()) {
- return model.aim()->index(model.rowAt(index), model.columnAt(index), model.rootIndex).data(*it);
- } else if (role == QLatin1String("hasModelChildren")) {
- return QVariant(model.aim()->hasChildren(model.aim()->index(model.rowAt(index), model.columnAt(index), model.rootIndex)));
- } else {
- return QVariant();
+ if (const QAbstractItemModel *aim = model.aim()) {
+ QHash<QByteArray, int>::const_iterator it = roleNames.find(role.toUtf8());
+ if (it != roleNames.end()) {
+ return aim->index(model.rowAt(index), model.columnAt(index),
+ model.rootIndex).data(*it);
+ } else if (role == QLatin1String("hasModelChildren")) {
+ return QVariant(aim->hasChildren(aim->index(model.rowAt(index),
+ model.columnAt(index),
+ model.rootIndex)));
+ }
}
+ return QVariant();
}
QVariant parentModelIndex(const QQmlAdaptorModel &model) const override
{
- return model
- ? QVariant::fromValue(model.aim()->parent(model.rootIndex))
- : QVariant();
+ if (const QAbstractItemModel *aim = model.aim())
+ return QVariant::fromValue(aim->parent(model.rootIndex));
+ return QVariant();
}
QVariant modelIndex(const QQmlAdaptorModel &model, int index) const override
{
- return model
- ? QVariant::fromValue(model.aim()->index(model.rowAt(index), model.columnAt(index), model.rootIndex))
- : QVariant();
+ if (const QAbstractItemModel *aim = model.aim())
+ return QVariant::fromValue(aim->index(model.rowAt(index), model.columnAt(index),
+ model.rootIndex));
+ return QVariant();
}
bool canFetchMore(const QQmlAdaptorModel &model) const override
{
- return model && model.aim()->canFetchMore(model.rootIndex);
+ if (const QAbstractItemModel *aim = model.aim())
+ return aim->canFetchMore(model.rootIndex);
+ return false;
}
void fetchMore(QQmlAdaptorModel &model) const override
{
- if (model)
- model.aim()->fetchMore(model.rootIndex);
+ if (QAbstractItemModel *aim = model.aim())
+ aim->fetchMore(model.rootIndex);
}
QQmlDelegateModelItem *createItem(
@@ -516,7 +527,8 @@ public:
setModelDataType<QQmlDMAbstractItemModelData>(&builder, this);
const QByteArray propertyType = QByteArrayLiteral("QVariant");
- const QHash<int, QByteArray> names = model.aim()->roleNames();
+ const QAbstractItemModel *aim = model.aim();
+ const QHash<int, QByteArray> names = aim ? aim->roleNames() : QHash<int, QByteArray>();
for (QHash<int, QByteArray>::const_iterator it = names.begin(), cend = names.end(); it != cend; ++it) {
const int propertyId = propertyRoles.count();
propertyRoles.append(it.key());
diff --git a/src/qmlworkerscript/qquickworkerscript.cpp b/src/qmlworkerscript/qquickworkerscript.cpp
index 9e4b3e1b46..72ae6d5bd4 100644
--- a/src/qmlworkerscript/qquickworkerscript.cpp
+++ b/src/qmlworkerscript/qquickworkerscript.cpp
@@ -130,6 +130,7 @@ struct WorkerScript : public QV4::ExecutionEngine {
QQuickWorkerScriptEnginePrivate *p = nullptr;
QUrl source;
QQuickWorkerScript *owner = nullptr;
+ QScopedPointer<QNetworkAccessManager> scriptLocalNAM;
int id = -1;
};
@@ -389,6 +390,16 @@ WorkerScript::WorkerScript(int id, QQuickWorkerScriptEnginePrivate *parent)
QV4::ScopedValue sendMessage(scope, QV4::FunctionObject::createBuiltinFunction(this, name, QQuickWorkerScriptEnginePrivate::method_sendMessage, 1));
api->put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("sendMessage"))), sendMessage);
globalObject->put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("WorkerScript"))), api);
+ networkAccessManager = [](QV4::ExecutionEngine *engine){
+ auto *workerScript = static_cast<WorkerScript *>(engine);
+ if (workerScript->scriptLocalNAM)
+ return workerScript->scriptLocalNAM.get();
+ if (auto *namFactory = workerScript->p->qmlengine->networkAccessManagerFactory())
+ workerScript->scriptLocalNAM.reset(namFactory->create(workerScript->p));
+ else
+ workerScript->scriptLocalNAM.reset(new QNetworkAccessManager(workerScript->p));
+ return workerScript->scriptLocalNAM.get();
+ };
}
int QQuickWorkerScriptEngine::registerWorkerScript(QQuickWorkerScript *owner)
diff --git a/src/quick/configure.json b/src/quick/configure.json
index 0cb1e7470b..f8277332dc 100644
--- a/src/quick/configure.json
+++ b/src/quick/configure.json
@@ -3,9 +3,11 @@
"depends": [
"core-private",
"qml-private",
+ "gui",
"gui-private",
"qmlmodels-private"
],
+ "condition": "module.gui",
"testDir": "../../config.tests",
"commandline": {
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index bc0d04c763..baef37a0ff 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -533,7 +533,7 @@ public:
void refWindow(QQuickWindow *);
void derefWindow();
- QQuickItem *subFocusItem;
+ QPointer<QQuickItem> subFocusItem;
void updateSubFocusItem(QQuickItem *scope, bool focus);
QTransform windowToItemTransform() const;
diff --git a/src/quick/scenegraph/qsgrhitextureglyphcache.cpp b/src/quick/scenegraph/qsgrhitextureglyphcache.cpp
index d0108bc56e..89c9ea4d5b 100644
--- a/src/quick/scenegraph/qsgrhitextureglyphcache.cpp
+++ b/src/quick/scenegraph/qsgrhitextureglyphcache.cpp
@@ -145,7 +145,9 @@ void QSGRhiTextureGlyphCache::prepareGlyphImage(QImage *img)
{
const int maskWidth = img->width();
const int maskHeight = img->height();
+#if Q_BYTE_ORDER != Q_BIG_ENDIAN
const bool supportsBgra = m_rhi->isTextureFormatSupported(QRhiTexture::BGRA8);
+#endif
m_bgra = false;
if (img->format() == QImage::Format_Mono) {