diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/3rdparty/masm/wtf/OSAllocatorPosix.cpp | 2 | ||||
-rw-r--r-- | src/imports/layouts/qquickstacklayout.cpp | 22 | ||||
-rw-r--r-- | src/imports/layouts/qquickstacklayout_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 19 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 13 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 11 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4reflect.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlincubator.cpp | 14 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycachecreator.cpp | 4 | ||||
-rw-r--r-- | src/quick/handlers/qquickpinchhandler.cpp | 3 | ||||
-rw-r--r-- | src/quick/items/qquickitemview.cpp | 2 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 6 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsggeometry.h | 1 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgrhitextureglyphcache.cpp | 5 | ||||
-rw-r--r-- | src/quickshapes/qquickshape.cpp | 8 |
15 files changed, 86 insertions, 31 deletions
diff --git a/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp b/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp index d54b7e9492..b5c5f6a2b0 100644 --- a/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp +++ b/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp @@ -225,7 +225,7 @@ void OSAllocator::commit(void* address, size_t bytes, bool writable, bool execut while (madvise(address, bytes, MADV_WILLNEED)) { if (errno != EAGAIN) - CRASH(); + break; // We don't have to crash here. MADV_WILLNEED is only advisory } #elif HAVE(MADV_FREE_REUSE) diff --git a/src/imports/layouts/qquickstacklayout.cpp b/src/imports/layouts/qquickstacklayout.cpp index 1d67d2058d..d127488b82 100644 --- a/src/imports/layouts/qquickstacklayout.cpp +++ b/src/imports/layouts/qquickstacklayout.cpp @@ -171,6 +171,7 @@ void QQuickStackLayout::itemChange(QQuickItem::ItemChange change, const QQuickIt QQuickLayout::itemChange(change, value); if (change == ItemChildRemovedChange) { + m_cachedItemSizeHints.remove(value.item); invalidate(); } else if (change == ItemChildAddedChange) { invalidate(); @@ -254,11 +255,12 @@ void QQuickStackLayout::setAlignment(QQuickItem * /*item*/, Qt::Alignment /*alig void QQuickStackLayout::invalidate(QQuickItem *childItem) { - const int indexOfChild = indexOf(childItem); - if (indexOfChild >= 0 && indexOfChild < m_cachedItemSizeHints.count()) { - m_cachedItemSizeHints[indexOfChild].min() = QSizeF(); - m_cachedItemSizeHints[indexOfChild].pref() = QSizeF(); - m_cachedItemSizeHints[indexOfChild].max() = QSizeF(); + ensureLayoutItemsUpdated(); + if (childItem) { + SizeHints &hints = m_cachedItemSizeHints[childItem]; + hints.min() = QSizeF(); + hints.pref() = QSizeF(); + hints.max() = QSizeF(); } for (int i = 0; i < Qt::NSizeHints; ++i) @@ -284,7 +286,6 @@ void QQuickStackLayout::updateLayoutItems() if (count != d->count) { d->count = count; emit countChanged(); - m_cachedItemSizeHints.resize(count); } for (int i = 0; i < count; ++i) { QQuickItem *child = itemAt(i); @@ -293,10 +294,13 @@ void QQuickStackLayout::updateLayoutItems() } } -QQuickStackLayout::SizeHints &QQuickStackLayout::cachedItemSizeHints(int index) const { - SizeHints &hints = m_cachedItemSizeHints[index]; +QQuickStackLayout::SizeHints &QQuickStackLayout::cachedItemSizeHints(int index) const +{ + QQuickItem *item = itemAt(index); + Q_ASSERT(item); + SizeHints &hints = m_cachedItemSizeHints[item]; // will create an entry if it doesn't exist if (!hints.min().isValid()) - QQuickStackLayout::collectItemSizeHints(itemAt(index), hints.array); + QQuickStackLayout::collectItemSizeHints(item, hints.array); return hints; } diff --git a/src/imports/layouts/qquickstacklayout_p.h b/src/imports/layouts/qquickstacklayout_p.h index 5349adfa36..d8feecc11b 100644 --- a/src/imports/layouts/qquickstacklayout_p.h +++ b/src/imports/layouts/qquickstacklayout_p.h @@ -95,7 +95,7 @@ private: QSizeF array[Qt::NSizeHints]; } SizeHints; - mutable QVector<SizeHints> m_cachedItemSizeHints; + mutable QHash<QQuickItem*, SizeHints> m_cachedItemSizeHints; mutable QSizeF m_cachedSizeHints[Qt::NSizeHints]; SizeHints &cachedItemSizeHints(int index) const; }; diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index f5dca60559..0a564fc6d5 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1892,6 +1892,25 @@ int ExecutionEngine::maxGCStackSize() const return m_maxGCStackSize; } +/*! + \internal + Returns \a length converted to int if its safe to + pass to \c Scope::alloc. + Otherwise it throws a RangeError, and returns 0. + */ +int ExecutionEngine::safeForAllocLength(qint64 len64) +{ + if (len64 < 0ll || len64 > qint64(std::numeric_limits<int>::max())) { + this->throwRangeError(QStringLiteral("Invalid array length.")); + return 0; + } + if (len64 > qint64(this->jsStackLimit - this->jsStackTop)) { + this->throwRangeError(QStringLiteral("Array too large for apply().")); + return 0; + } + return len64; +} + ReturnedValue ExecutionEngine::global() { return globalObject->asReturnedValue(); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index efe44a324c..dd6e6ed279 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -655,6 +655,7 @@ public: int maxGCStackSize() const; bool checkStackLimits(); + int safeForAllocLength(qint64 len64); bool canJIT(Function *f = nullptr) { @@ -723,6 +724,9 @@ public: QQmlRefPointer<ExecutableCompilationUnit> loadModule(const QUrl &_url, const ExecutableCompilationUnit *referrer = nullptr); private: + template<int Frames> + friend struct ExecutionEngineCallDepthRecorder; + #if QT_CONFIG(qml_debug) QScopedPointer<QV4::Debugging::Debugger> m_debugger; QScopedPointer<QV4::Profiling::Profiler> m_profiler; @@ -753,14 +757,17 @@ private: }; #define CHECK_STACK_LIMITS(v4) if ((v4)->checkStackLimits()) return Encode::undefined(); \ - ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4); + ExecutionEngineCallDepthRecorder<1> _executionEngineCallDepthRecorder(v4); +template<int Frames = 1> struct ExecutionEngineCallDepthRecorder { ExecutionEngine *ee; - ExecutionEngineCallDepthRecorder(ExecutionEngine *e): ee(e) { ++ee->callDepth; } - ~ExecutionEngineCallDepthRecorder() { --ee->callDepth; } + ExecutionEngineCallDepthRecorder(ExecutionEngine *e): ee(e) { ee->callDepth += Frames; } + ~ExecutionEngineCallDepthRecorder() { ee->callDepth -= Frames; } + + bool hasOverflow() const { return ee->callDepth >= ExecutionEngine::maxCallDepth; } }; inline bool ExecutionEngine::checkStackLimits() diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index cdb3b8942b..8dafe251e0 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -364,15 +364,10 @@ ReturnedValue FunctionPrototype::method_apply(const QV4::FunctionObject *b, cons if (!arr) return v4->throwTypeError(); - 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); + const uint len = v4->safeForAllocLength(arr->getLength()); + CHECK_EXCEPTION(); + Value *arguments = scope.alloc<Scope::Uninitialized>(len); if (len) { if (ArgumentsObject::isNonStrictArgumentsObject(arr) && !arr->cast<ArgumentsObject>()->fullyCreated()) { diff --git a/src/qml/jsruntime/qv4reflect.cpp b/src/qml/jsruntime/qv4reflect.cpp index 2a6c61f044..39a0b03dec 100644 --- a/src/qml/jsruntime/qv4reflect.cpp +++ b/src/qml/jsruntime/qv4reflect.cpp @@ -76,7 +76,10 @@ struct CallArgs { static CallArgs createListFromArrayLike(Scope &scope, const Object *o) { - int len = o->getLength(); + int len = scope.engine->safeForAllocLength(o->getLength()); + if (scope.engine->hasException) + return {nullptr, 0}; + Value *arguments = scope.alloc(len); for (int i = 0; i < len; ++i) { diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp index 244f9ad292..3cbd5e17d2 100644 --- a/src/qml/qml/qqmlincubator.cpp +++ b/src/qml/qml/qqmlincubator.cpp @@ -279,6 +279,20 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i) // get a copy of the engine pointer as it might get reset; QQmlEnginePrivate *enginePriv = this->enginePriv; + // Incubating objects takes quite a bit more stack space than our usual V4 function + enum { EstimatedSizeInV4Frames = 2 }; + QV4::ExecutionEngineCallDepthRecorder<EstimatedSizeInV4Frames> callDepthRecorder( + compilationUnit->engine); + if (callDepthRecorder.hasOverflow()) { + QQmlError error; + error.setMessageType(QtCriticalMsg); + error.setUrl(compilationUnit->url()); + error.setDescription(QQmlComponent::tr("Maximum call stack size exceeded.")); + errors << error; + progress = QQmlIncubatorPrivate::Completed; + goto finishIncubate; + } + if (!vmeGuard.isOK()) { QQmlError error; error.setMessageType(QtInfoMsg); diff --git a/src/qml/qml/qqmlpropertycachecreator.cpp b/src/qml/qml/qqmlpropertycachecreator.cpp index 1579fd3336..de02636d95 100644 --- a/src/qml/qml/qqmlpropertycachecreator.cpp +++ b/src/qml/qml/qqmlpropertycachecreator.cpp @@ -115,8 +115,10 @@ bool QQmlBindingInstantiationContext::resolveInstantiatingProperty() return true; } + if (!referencingObjectPropertyCache) + return false; + Q_ASSERT(referencingObjectIndex >= 0); - Q_ASSERT(referencingObjectPropertyCache); Q_ASSERT(instantiatingBinding->propertyNameIndex != 0); bool notInRevision = false; diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp index 7232f0bb2f..16cf2c8100 100644 --- a/src/quick/handlers/qquickpinchhandler.cpp +++ b/src/quick/handlers/qquickpinchhandler.cpp @@ -543,6 +543,9 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event) The translation of the gesture \l centroid. It is \c (0, 0) when the gesture begins. + + \note On some touchpads, such as on a \macos trackpad, native gestures do + not generate any translation values, and this property stays at \c (0, 0). */ QT_END_NAMESPACE diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index f8ad168a17..29afaae93b 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -290,8 +290,6 @@ void QQuickItemView::setDelegate(QQmlComponent *delegate) if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model)) { int oldCount = dataModel->count(); dataModel->setDelegate(delegate); - if (isComponentComplete()) - d->applyDelegateChange(); if (oldCount != dataModel->count()) emit countChanged(); } diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 50b7a333c7..8ab69603ad 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1494,7 +1494,11 @@ QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QWindow *parent) } /*! - \internal + Constructs a window for displaying a QML scene, whose rendering will + be controlled by the \a control object. + Please refer to QQuickRenderControl's documentation for more information. + + \since 5.4 */ QQuickWindow::QQuickWindow(QQuickRenderControl *control) : QWindow(*(new QQuickWindowPrivate), nullptr) diff --git a/src/quick/scenegraph/coreapi/qsggeometry.h b/src/quick/scenegraph/coreapi/qsggeometry.h index d17915a842..685ac1cd95 100644 --- a/src/quick/scenegraph/coreapi/qsggeometry.h +++ b/src/quick/scenegraph/coreapi/qsggeometry.h @@ -202,6 +202,7 @@ public: void setLineWidth(float w); private: + Q_DISABLE_COPY_MOVE(QSGGeometry) friend class QSGGeometryData; int m_drawing_mode; diff --git a/src/quick/scenegraph/qsgrhitextureglyphcache.cpp b/src/quick/scenegraph/qsgrhitextureglyphcache.cpp index 89c9ea4d5b..c35d5b0705 100644 --- a/src/quick/scenegraph/qsgrhitextureglyphcache.cpp +++ b/src/quick/scenegraph/qsgrhitextureglyphcache.cpp @@ -233,7 +233,10 @@ void QSGRhiTextureGlyphCache::endFillTexture() int QSGRhiTextureGlyphCache::glyphPadding() const { - return 1; + if (m_format == QFontEngine::Format_Mono) + return 8; + else + return 1; } int QSGRhiTextureGlyphCache::maxTextureWidth() const diff --git a/src/quickshapes/qquickshape.cpp b/src/quickshapes/qquickshape.cpp index bdfd5e3f76..f9c0968c7e 100644 --- a/src/quickshapes/qquickshape.cpp +++ b/src/quickshapes/qquickshape.cpp @@ -1522,6 +1522,7 @@ static void generateGradientColorTable(const QQuickShapeGradientCacheKey &gradie { int pos = 0; const QGradientStops &s = gradient.stops; + Q_ASSERT(!s.isEmpty()); const bool colorInterpolation = true; uint alpha = qRound(opacity * 256); @@ -1559,8 +1560,6 @@ static void generateGradientColorTable(const QQuickShapeGradientCacheKey &gradie current_color = next_color; } - Q_ASSERT(s.size() > 0); - uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(s[sLast].second.rgba(), alpha))); for ( ; pos < size; ++pos) colorTable[pos] = last_color; @@ -1595,7 +1594,10 @@ QSGTexture *QQuickShapeGradientCache::get(const QQuickShapeGradientCacheKey &gra if (!tx) { static const int W = 1024; // texture size is 1024x1 QImage gradTab(W, 1, QImage::Format_RGBA8888_Premultiplied); - generateGradientColorTable(grad, reinterpret_cast<uint *>(gradTab.bits()), W, 1.0f); + if (!grad.stops.isEmpty()) + generateGradientColorTable(grad, reinterpret_cast<uint *>(gradTab.bits()), W, 1.0f); + else + gradTab.fill(Qt::black); tx = new QSGPlainTexture; tx->setImage(gradTab); switch (grad.spread) { |