From 67d783622d7a180da89af4c1fb57c6973e5b4386 Mon Sep 17 00:00:00 2001 From: Kavindra Palaraja Date: Wed, 28 Dec 2016 10:59:05 +0100 Subject: Removed auto-generated links to internal classes QQmlExtensionInterface and QQmlTypesExtensionInterface are internal classes that are not relevant from an external API perspective, but merely an implementation detail of the plugin loading mechanism in QML. Task-number: QTBUG-57190 Change-Id: I5fdfe26f1b74c4782040aaadd3ee13b9c92153eb Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlextensionplugin.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/qml/qml/qqmlextensionplugin.cpp b/src/qml/qml/qqmlextensionplugin.cpp index ca19691e93..097fa71200 100644 --- a/src/qml/qml/qqmlextensionplugin.cpp +++ b/src/qml/qml/qqmlextensionplugin.cpp @@ -117,4 +117,14 @@ void QQmlExtensionPlugin::initializeEngine(QQmlEngine *engine, const char *uri) Q_UNUSED(uri); } +/*! + \class QQmlExtensionInterface + \internal + \inmodule QtQml + + \class QQmlTypesExtensionInterface + \internal + \inmodule QtQml +*/ + QT_END_NAMESPACE -- cgit v1.2.3 From d2eaf438ac44a39aab6ac6ecc23e9ebb39aa58ac Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 22 Dec 2016 12:50:54 +0100 Subject: Get rid of the GCBlocker It's a hack we needed when we still had a conservative GC, but it is not required anymore. The only thing we still need is the protection against running the GC recursively. Change-Id: I55cd51d4929c828db5b61b38e781467c5bf77314 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4engine.cpp | 2 -- src/qml/jsruntime/qv4script.cpp | 2 -- src/qml/memory/qv4mm.cpp | 10 ---------- src/qml/memory/qv4mm_p.h | 22 ---------------------- 4 files changed, 36 deletions(-) diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 2b90b43eab..8c4c39b774 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -158,8 +158,6 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) } Q_ASSERT(maxCallDepth > 0); - MemoryManager::GCBlocker gcBlocker(memoryManager); - if (!factory) { #if QT_CONFIG(qml_interpreter) bool jitDisabled = true; diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 5d7df9a9d7..fe8f8474e4 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -88,8 +88,6 @@ void Script::parse() ExecutionEngine *v4 = scope->engine(); Scope valueScope(v4); - MemoryManager::GCBlocker gcBlocker(v4->memoryManager); - IR::Module module(v4->debugger() != 0); QQmlJS::Engine ee, *engine = ⅇ diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 606d3ec162..8732b02685 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -565,16 +565,6 @@ void MemoryManager::sweep(bool lastSweep) } } -bool MemoryManager::isGCBlocked() const -{ - return m_d->gcBlocked; -} - -void MemoryManager::setGCBlocked(bool blockGC) -{ - m_d->gcBlocked = blockGC; -} - void MemoryManager::runGC() { if (m_d->gcBlocked) { diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index dfa0d85dff..86a0ba2735 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -76,26 +76,6 @@ class Q_QML_EXPORT MemoryManager public: struct Data; - class GCBlocker - { - public: - GCBlocker(MemoryManager *mm) - : mm(mm) - , wasBlocked(mm->isGCBlocked()) - { - mm->setGCBlocked(true); - } - - ~GCBlocker() - { - mm->setGCBlocked(wasBlocked); - } - - private: - MemoryManager *mm; - bool wasBlocked; - }; - public: MemoryManager(ExecutionEngine *engine); ~MemoryManager(); @@ -309,8 +289,6 @@ public: return t->d(); } - bool isGCBlocked() const; - void setGCBlocked(bool blockGC); void runGC(); void dumpStats() const; -- cgit v1.2.3 From b2501b0bda6a0bf4f4d5ce19e7efeda236bcbe9a Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 21 Nov 2016 13:39:38 +0100 Subject: QQuickWindow flushFrameSynchronousEvents: don't hover if nothing dirty An optimization revising 6f84a09dfbd15aac023580cf06e7b8c24f3b524c Calling hoverMoveEvent every frame is too inefficient when an item subclass is actually doing something there. For example, any QtQuick-based Wayland compositor needs to notify its client windows when hover state changes, so calling this method too often would impose extra work to double-check whether it really changed or not. Change-Id: I98b40a2083700e7a50820bd13154247444249e59 Reviewed-by: Robin Burchell --- src/quick/items/qquickwindow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 155a52bd9b..a58912e38f 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -2081,11 +2081,12 @@ void QQuickWindowPrivate::flushFrameSynchronousEvents() ut->startAnimations(); } - // Once per frame, send a synthetic hover, in case items have changed position. + // Once per frame, if any items are dirty, send a synthetic hover, + // in case items have changed position, visibility, etc. // For instance, during animation (including the case of a ListView // whose delegates contain MouseAreas), a MouseArea needs to know // whether it has moved into a position where it is now under the cursor. - if (!q->mouseGrabberItem() && !lastMousePosition.isNull()) { + if (!q->mouseGrabberItem() && !lastMousePosition.isNull() && dirtyItemList) { bool accepted = false; bool delivered = deliverHoverEvent(contentItem, lastMousePosition, lastMousePosition, QGuiApplication::keyboardModifiers(), 0, accepted); if (!delivered) -- cgit v1.2.3 From bb594453f9cb96bf8f2975d4a8aa5379cfc46e23 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Sat, 25 Jun 2016 12:16:25 +0200 Subject: Flickable: add horizontal/verticalOvershoot properties [ChangeLog][QtQuick][Flickable] Added horizontalOvershoot and verticalOvershoot properties that can be used for implementing boundary actions and effects. Task-number: QTBUG-38515 Change-Id: I06379348a67d03507b56788d6fc7020bbb2d375f Reviewed-by: Robin Burchell --- src/quick/items/qquickflickable.cpp | 80 ++++++++- src/quick/items/qquickflickable_p.h | 9 + src/quick/items/qquickflickable_p_p.h | 3 +- src/quick/items/qquickitemsmodule.cpp | 1 + .../auto/quick/qquickflickable/data/overshoot.qml | 79 +++++++++ .../qquickflickable/data/overshoot_reentrant.qml | 55 ++++++ .../quick/qquickflickable/tst_qquickflickable.cpp | 196 +++++++++++++++++++++ 7 files changed, 420 insertions(+), 3 deletions(-) create mode 100644 tests/auto/quick/qquickflickable/data/overshoot.qml create mode 100644 tests/auto/quick/qquickflickable/data/overshoot_reentrant.qml diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 00a1306627..4ab604b30f 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -1570,12 +1570,52 @@ void QQuickFlickablePrivate::replayDelayedPress() //XXX pixelAligned ignores the global position of the Flickable, i.e. assumes Flickable itself is pixel aligned. void QQuickFlickablePrivate::setViewportX(qreal x) { - contentItem->setX(pixelAligned ? -Round(-x) : x); + Q_Q(QQuickFlickable); + if (pixelAligned) + x = -Round(-x); + + contentItem->setX(x); + if (contentItem->x() != x) + return; // reentered + + const qreal maxX = q->maxXExtent(); + const qreal minX = q->minXExtent(); + + qreal overshoot = 0.0; + if (x <= maxX) + overshoot = maxX - x; + else if (x >= minX) + overshoot = minX - x; + + if (overshoot != hData.overshoot) { + hData.overshoot = overshoot; + emit q->horizontalOvershootChanged(); + } } void QQuickFlickablePrivate::setViewportY(qreal y) { - contentItem->setY(pixelAligned ? -Round(-y) : y); + Q_Q(QQuickFlickable); + if (pixelAligned) + y = -Round(-y); + + contentItem->setY(y); + if (contentItem->y() != y) + return; // reentered + + const qreal maxY = q->maxYExtent(); + const qreal minY = q->minYExtent(); + + qreal overshoot = 0.0; + if (y <= maxY) + overshoot = maxY - y; + else if (y >= minY) + overshoot = minY - y; + + if (overshoot != vData.overshoot) { + vData.overshoot = overshoot; + emit q->verticalOvershootChanged(); + } } void QQuickFlickable::timerEvent(QTimerEvent *event) @@ -1841,6 +1881,8 @@ QQmlListProperty QQuickFlickable::flickableChildren() beyond the boundary of the Flickable, and can overshoot the boundary when flicked. \endlist + + \sa horizontalOvershoot, verticalOvershoot */ QQuickFlickable::BoundsBehavior QQuickFlickable::boundsBehavior() const { @@ -2638,4 +2680,38 @@ void QQuickFlickablePrivate::updateVelocity() emit q->verticalVelocityChanged(); } +/*! + \qmlproperty real QtQuick::Flickable::horizontalOvershoot + \since 5.9 + + This property holds the horizontal overshoot, that is, the horizontal distance by + which the contents has been dragged or flicked past the bounds of the flickable. + The value is negative when the content is dragged or flicked beyond the beginning, + and positive when beyond the end; \c 0.0 otherwise. + + \sa verticalOvershoot, boundsBehavior +*/ +qreal QQuickFlickable::horizontalOvershoot() const +{ + Q_D(const QQuickFlickable); + return d->hData.overshoot; +} + +/*! + \qmlproperty real QtQuick::Flickable::verticalOvershoot + \since 5.9 + + This property holds the vertical overshoot, that is, the vertical distance by + which the contents has been dragged or flicked past the bounds of the flickable. + The value is negative when the content is dragged or flicked beyond the beginning, + and positive when beyond the end; \c 0.0 otherwise. + + \sa horizontalOvershoot, boundsBehavior +*/ +qreal QQuickFlickable::verticalOvershoot() const +{ + Q_D(const QQuickFlickable); + return d->vData.overshoot; +} + QT_END_NAMESPACE diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h index 7384c7271a..78c8271525 100644 --- a/src/quick/items/qquickflickable_p.h +++ b/src/quick/items/qquickflickable_p.h @@ -106,6 +106,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickFlickable : public QQuickItem Q_PROPERTY(bool pixelAligned READ pixelAligned WRITE setPixelAligned NOTIFY pixelAlignedChanged) + Q_PROPERTY(qreal horizontalOvershoot READ horizontalOvershoot NOTIFY horizontalOvershootChanged REVISION 9) + Q_PROPERTY(qreal verticalOvershoot READ verticalOvershoot NOTIFY verticalOvershootChanged REVISION 9) + Q_PROPERTY(QQmlListProperty flickableData READ flickableData) Q_PROPERTY(QQmlListProperty flickableChildren READ flickableChildren) Q_CLASSINFO("DefaultProperty", "flickableData") @@ -201,6 +204,9 @@ public: bool pixelAligned() const; void setPixelAligned(bool align); + qreal horizontalOvershoot() const; + qreal verticalOvershoot() const; + Q_INVOKABLE void resizeContent(qreal w, qreal h, QPointF center); Q_INVOKABLE void returnToBounds(); Q_INVOKABLE void flick(qreal xVelocity, qreal yVelocity); @@ -243,6 +249,8 @@ Q_SIGNALS: void dragStarted(); void dragEnded(); void pixelAlignedChanged(); + Q_REVISION(9) void horizontalOvershootChanged(); + Q_REVISION(9) void verticalOvershootChanged(); protected: bool childMouseEventFilter(QQuickItem *, QEvent *) Q_DECL_OVERRIDE; @@ -286,6 +294,7 @@ protected: private: Q_DISABLE_COPY(QQuickFlickable) Q_DECLARE_PRIVATE(QQuickFlickable) + friend class QQuickFlickableContentItem; friend class QQuickFlickableVisibleArea; friend class QQuickFlickableReboundTransition; }; diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h index 0c3bc21071..1ceff22dfc 100644 --- a/src/quick/items/qquickflickable_p_p.h +++ b/src/quick/items/qquickflickable_p_p.h @@ -101,7 +101,7 @@ public: : move(fp, func) , transitionToBounds(0) , viewSize(-1), lastPos(0), previousDragDelta(0), velocity(0), startMargin(0), endMargin(0) - , origin(0) + , origin(0), overshoot(0) , transitionTo(0) , continuousFlickVelocity(0), velocityTime(), vTime(0) , smoothVelocity(fp), atEnd(false), atBeginning(true) @@ -148,6 +148,7 @@ public: qreal startMargin; qreal endMargin; qreal origin; + qreal overshoot; qreal transitionTo; qreal continuousFlickVelocity; QElapsedTimer velocityTime; diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index b0ddbb0034..b8db5d76e4 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -374,6 +374,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType("QtQuick", 2, 8, "BorderImageMesh"); #endif + qmlRegisterType(uri, 2, 9, "Flickable"); qmlRegisterType(uri, 2, 9, "MouseArea"); } diff --git a/tests/auto/quick/qquickflickable/data/overshoot.qml b/tests/auto/quick/qquickflickable/data/overshoot.qml new file mode 100644 index 0000000000..4235156479 --- /dev/null +++ b/tests/auto/quick/qquickflickable/data/overshoot.qml @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 + +Flickable { + width: 200; height: 200 + contentWidth: rect.width; contentHeight: rect.height + + property real minContentY: 0 + property real maxContentY: 0 + onContentYChanged: { + minContentY = Math.min(contentY, minContentY) + maxContentY = Math.max(contentY, maxContentY) + } + + property real minContentX: 0 + property real maxContentX: 0 + onContentXChanged: { + minContentX = Math.min(contentX, minContentX) + maxContentX = Math.max(contentX, maxContentX) + } + + property real minVerticalOvershoot: 0 + property real maxVerticalOvershoot: 0 + onVerticalOvershootChanged: { + minVerticalOvershoot = Math.min(verticalOvershoot, minVerticalOvershoot) + maxVerticalOvershoot = Math.max(verticalOvershoot, maxVerticalOvershoot) + } + + property real minHorizontalOvershoot: 0 + property real maxHorizontalOvershoot: 0 + onHorizontalOvershootChanged: { + minHorizontalOvershoot = Math.min(horizontalOvershoot, minHorizontalOvershoot) + maxHorizontalOvershoot = Math.max(horizontalOvershoot, maxHorizontalOvershoot) + } + + function reset() { + minContentY = contentY + maxContentY = contentY + minContentX = contentX + maxContentX = contentX + minVerticalOvershoot = 0 + maxVerticalOvershoot = 0 + minHorizontalOvershoot = 0 + maxHorizontalOvershoot = 0 + } + + Rectangle { + id: rect + color: "red" + width: 400; height: 400 + } +} diff --git a/tests/auto/quick/qquickflickable/data/overshoot_reentrant.qml b/tests/auto/quick/qquickflickable/data/overshoot_reentrant.qml new file mode 100644 index 0000000000..bc7abba25a --- /dev/null +++ b/tests/auto/quick/qquickflickable/data/overshoot_reentrant.qml @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 + +Flickable { + width: 200; height: 200 + contentWidth: rect.width; contentHeight: rect.height + + property real contentPosAdjustment: 0.0 + + onContentXChanged: { + var adjustment = contentPosAdjustment + contentPosAdjustment = 0.0 + contentX += adjustment + } + + onContentYChanged: { + var adjustment = contentPosAdjustment + contentPosAdjustment = 0.0 + contentY += adjustment + } + + Rectangle { + id: rect + border.color: "red" + border.width: 5 + width: 400; height: 400 + } +} diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index 942e99018f..1ad691d1c1 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -95,6 +95,9 @@ private slots: void ratios_smallContent(); void contentXYNotTruncatedToInt(); void keepGrab(); + void overshoot(); + void overshoot_data(); + void overshoot_reentrant(); private: void flickWithTouch(QQuickWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to); @@ -2037,6 +2040,199 @@ void tst_qquickflickable::keepGrab() QVERIFY(flickable->contentY() != 0.0); } +Q_DECLARE_METATYPE(QQuickFlickable::BoundsBehavior) + +void tst_qquickflickable::overshoot() +{ + QFETCH(QQuickFlickable::BoundsBehavior, boundsBehavior); + + QScopedPointer window(new QQuickView); + window->setSource(testFileUrl("overshoot.qml")); + window->show(); + + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + + QQuickFlickable *flickable = qobject_cast(window->rootObject()); + QVERIFY(flickable); + + QCOMPARE(flickable->width(), 200.0); + QCOMPARE(flickable->height(), 200.0); + QCOMPARE(flickable->contentWidth(), 400.0); + QCOMPARE(flickable->contentHeight(), 400.0); + + flickable->setBoundsBehavior(boundsBehavior); + + // drag past the beginning + QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(10, 10)); + QTest::mouseMove(window.data(), QPoint(20, 20)); + QTest::mouseMove(window.data(), QPoint(30, 30)); + QTest::mouseMove(window.data(), QPoint(40, 40)); + QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(50, 50)); + + if (boundsBehavior & QQuickFlickable::DragOverBounds) { + QVERIFY(flickable->property("minVerticalOvershoot").toReal() < 0.0); + QVERIFY(flickable->property("minHorizontalOvershoot").toReal() < 0.0); + QCOMPARE(flickable->property("minContentY").toReal(), + flickable->property("minVerticalOvershoot").toReal()); + QCOMPARE(flickable->property("minContentX").toReal(), + flickable->property("minHorizontalOvershoot").toReal()); + } else { + QCOMPARE(flickable->property("minContentY").toReal(), 0.0); + QCOMPARE(flickable->property("minContentX").toReal(), 0.0); + QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("minHorizontalOvershoot").toReal(), 0.0); + } + QCOMPARE(flickable->property("maxContentY").toReal(), 0.0); + QCOMPARE(flickable->property("maxContentX").toReal(), 0.0); + QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("maxHorizontalOvershoot").toReal(), 0.0); + + flickable->setContentX(20.0); + flickable->setContentY(20.0); + QMetaObject::invokeMethod(flickable, "reset"); + + // flick past the beginning + flick(window.data(), QPoint(10, 10), QPoint(50, 50), 100); + QTRY_VERIFY(!flickable->property("flicking").toBool()); + + if (boundsBehavior & QQuickFlickable::OvershootBounds) { + QVERIFY(flickable->property("minVerticalOvershoot").toReal() < 0.0); + QVERIFY(flickable->property("minHorizontalOvershoot").toReal() < 0.0); + QCOMPARE(flickable->property("minContentY").toReal(), + flickable->property("minVerticalOvershoot").toReal()); + QCOMPARE(flickable->property("minContentX").toReal(), + flickable->property("minHorizontalOvershoot").toReal()); + } else { + QCOMPARE(flickable->property("minContentY").toReal(), 0.0); + QCOMPARE(flickable->property("minContentX").toReal(), 0.0); + QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("minHorizontalOvershoot").toReal(), 0.0); + } + QCOMPARE(flickable->property("maxContentY").toReal(), 20.0); + QCOMPARE(flickable->property("maxContentX").toReal(), 20.0); + QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("maxHorizontalOvershoot").toReal(), 0.0); + + flickable->setContentX(200.0); + flickable->setContentY(200.0); + QMetaObject::invokeMethod(flickable, "reset"); + + // drag past the end + QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(50, 50)); + QTest::mouseMove(window.data(), QPoint(40, 40)); + QTest::mouseMove(window.data(), QPoint(30, 30)); + QTest::mouseMove(window.data(), QPoint(20, 20)); + QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(10, 10)); + + if (boundsBehavior & QQuickFlickable::DragOverBounds) { + QVERIFY(flickable->property("maxVerticalOvershoot").toReal() > 0.0); + QVERIFY(flickable->property("maxHorizontalOvershoot").toReal() > 0.0); + QCOMPARE(flickable->property("maxContentY").toReal() - 200.0, + flickable->property("maxVerticalOvershoot").toReal()); + QCOMPARE(flickable->property("maxContentX").toReal() - 200.0, + flickable->property("maxHorizontalOvershoot").toReal()); + } else { + QCOMPARE(flickable->property("maxContentY").toReal(), 200.0); + QCOMPARE(flickable->property("maxContentX").toReal(), 200.0); + QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("maxHorizontalOvershoot").toReal(), 0.0); + } + QCOMPARE(flickable->property("minContentY").toReal(), 200.0); + QCOMPARE(flickable->property("minContentX").toReal(), 200.0); + QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("minHorizontalOvershoot").toReal(), 0.0); + + flickable->setContentX(180.0); + flickable->setContentY(180.0); + QMetaObject::invokeMethod(flickable, "reset"); + + // flick past the end + flick(window.data(), QPoint(50, 50), QPoint(10, 10), 100); + QTRY_VERIFY(!flickable->property("flicking").toBool()); + + if (boundsBehavior & QQuickFlickable::OvershootBounds) { + QVERIFY(flickable->property("maxVerticalOvershoot").toReal() > 0.0); + QVERIFY(flickable->property("maxHorizontalOvershoot").toReal() > 0.0); + QCOMPARE(flickable->property("maxContentY").toReal() - 200.0, + flickable->property("maxVerticalOvershoot").toReal()); + QCOMPARE(flickable->property("maxContentX").toReal() - 200.0, + flickable->property("maxHorizontalOvershoot").toReal()); + } else { + QCOMPARE(flickable->property("maxContentY").toReal(), 200.0); + QCOMPARE(flickable->property("maxContentX").toReal(), 200.0); + QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("maxHorizontalOvershoot").toReal(), 0.0); + } + QCOMPARE(flickable->property("minContentY").toReal(), 180.0); + QCOMPARE(flickable->property("minContentX").toReal(), 180.0); + QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("minHorizontalOvershoot").toReal(), 0.0); +} + +void tst_qquickflickable::overshoot_data() +{ + QTest::addColumn("boundsBehavior"); + + QTest::newRow("StopAtBounds") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::StopAtBounds); + QTest::newRow("DragOverBounds") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragOverBounds); + QTest::newRow("OvershootBounds") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::OvershootBounds); + QTest::newRow("DragAndOvershootBounds") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragAndOvershootBounds); +} + +void tst_qquickflickable::overshoot_reentrant() +{ + QScopedPointer window(new QQuickView); + window->setSource(testFileUrl("overshoot_reentrant.qml")); + window->show(); + + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + + QQuickFlickable *flickable = qobject_cast(window->rootObject()); + QVERIFY(flickable); + + // horizontal + flickable->setContentX(-10.0); + QCOMPARE(flickable->contentX(), -10.0); + QCOMPARE(flickable->horizontalOvershoot(), -10.0); + + flickable->setProperty("contentPosAdjustment", -5.0); + flickable->setContentX(-20.0); + QCOMPARE(flickable->contentX(), -25.0); + QCOMPARE(flickable->horizontalOvershoot(), -25.0); + + flickable->setContentX(210); + QCOMPARE(flickable->contentX(), 210.0); + QCOMPARE(flickable->horizontalOvershoot(), 10.0); + + flickable->setProperty("contentPosAdjustment", 5.0); + flickable->setContentX(220.0); + QCOMPARE(flickable->contentX(), 225.0); + QCOMPARE(flickable->horizontalOvershoot(), 25.0); + + // vertical + flickable->setContentY(-10.0); + QCOMPARE(flickable->contentY(), -10.0); + QCOMPARE(flickable->verticalOvershoot(), -10.0); + + flickable->setProperty("contentPosAdjustment", -5.0); + flickable->setContentY(-20.0); + QCOMPARE(flickable->contentY(), -25.0); + QCOMPARE(flickable->verticalOvershoot(), -25.0); + + flickable->setContentY(210); + QCOMPARE(flickable->contentY(), 210.0); + QCOMPARE(flickable->verticalOvershoot(), 10.0); + + flickable->setProperty("contentPosAdjustment", 5.0); + flickable->setContentY(220.0); + QCOMPARE(flickable->contentY(), 225.0); + QCOMPARE(flickable->verticalOvershoot(), 25.0); +} + QTEST_MAIN(tst_qquickflickable) #include "tst_qquickflickable.moc" -- cgit v1.2.3 From 3f6d82715dda8dd06f6bddf2ed89e89640f63a2e Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Wed, 30 Nov 2016 09:40:23 +0100 Subject: Add TextInput::textEdited() [ChangeLog][QtQuick][TextInput] Added textEdited() signal to distinguish user edits from programmatical text changes. Change-Id: I1d78499e3e11f9f1cab80ce3b0a6d9f2713219f4 Task-number: QTBUG-57203 Reviewed-by: Mitch Curtis Reviewed-by: Shawn Rutledge --- src/quick/items/qquickitemsmodule.cpp | 1 + src/quick/items/qquicktextinput.cpp | 15 ++++++- src/quick/items/qquicktextinput_p.h | 1 + .../quick/qquicktextinput/tst_qquicktextinput.cpp | 52 ++++++++++++++++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index b8db5d76e4..ee7b566266 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -376,6 +376,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType(uri, 2, 9, "Flickable"); qmlRegisterType(uri, 2, 9, "MouseArea"); + qmlRegisterType(uri, 2, 9, "TextInput"); } static void initResources() diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 27f3dcecfa..e9f88ae7f0 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -1152,6 +1152,17 @@ bool QQuickTextInput::hasAcceptableInput() const The corresponding handler is \c onEditingFinished. */ +/*! + \qmlsignal QtQuick::TextInput::textEdited() + \since 5.9 + + This signal is emitted whenever the text is edited. Unlike \c textChanged(), + this signal is not emitted when the text is changed programmatically, for example, + by changing the value of the \c text property or by calling \c clear(). + + The corresponding handler is \c onTextEdited. +*/ + #if QT_CONFIG(im) Qt::InputMethodHints QQuickTextInputPrivate::effectiveInputMethodHints() const { @@ -3499,7 +3510,7 @@ void QQuickTextInputPrivate::selectWordAtPos(int cursor) The \a update value is currently unused. */ -bool QQuickTextInputPrivate::finishChange(int validateFromState, bool update, bool /*edited*/) +bool QQuickTextInputPrivate::finishChange(int validateFromState, bool update, bool edited) { Q_Q(QQuickTextInput); @@ -3570,6 +3581,8 @@ bool QQuickTextInputPrivate::finishChange(int validateFromState, bool update, bo m_preeditDirty = false; #endif alignmentChanged = determineHorizontalAlignment(); + if (edited) + emit q->textEdited(); emit q->textChanged(); } diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h index f4545e1574..c4da807471 100644 --- a/src/quick/items/qquicktextinput_p.h +++ b/src/quick/items/qquicktextinput_p.h @@ -319,6 +319,7 @@ Q_SIGNALS: void accepted(); void acceptableInputChanged(); Q_REVISION(2) void editingFinished(); + Q_REVISION(9) void textEdited(); void colorChanged(); void selectionColorChanged(); void selectedTextColorChanged(); diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp index 1451f8e2fc..67921e1fd0 100644 --- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp +++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp @@ -135,6 +135,7 @@ private slots: void signal_accepted(); void signal_editingfinished(); + void signal_textEdited(); void passwordCharacter(); void cursorDelegate_data(); @@ -2441,6 +2442,57 @@ void tst_qquicktextinput::signal_editingfinished() QTRY_COMPARE(editingFinished2Spy.count(), 1); } +void tst_qquicktextinput::signal_textEdited() +{ + QQuickWindow window; + window.show(); + window.requestActivate(); + QTest::qWaitForWindowActive(&window); + + QQuickTextInput *input = new QQuickTextInput(window.contentItem()); + QVERIFY(input); + + QSignalSpy textChangedSpy(input, SIGNAL(textChanged())); + QVERIFY(textChangedSpy.isValid()); + + QSignalSpy textEditedSpy(input, SIGNAL(textEdited())); + QVERIFY(textEditedSpy.isValid()); + + input->forceActiveFocus(); + QTRY_VERIFY(input->hasActiveFocus()); + + int textChanges = 0; + int textEdits = 0; + + QTest::keyClick(&window, Qt::Key_A); + QCOMPARE(textChangedSpy.count(), ++textChanges); + QCOMPARE(textEditedSpy.count(), ++textEdits); + + QTest::keyClick(&window, Qt::Key_B); + QCOMPARE(textChangedSpy.count(), ++textChanges); + QCOMPARE(textEditedSpy.count(), ++textEdits); + + QTest::keyClick(&window, Qt::Key_C); + QCOMPARE(textChangedSpy.count(), ++textChanges); + QCOMPARE(textEditedSpy.count(), ++textEdits); + + QTest::keyClick(&window, Qt::Key_Space); + QCOMPARE(textChangedSpy.count(), ++textChanges); + QCOMPARE(textEditedSpy.count(), ++textEdits); + + QTest::keyClick(&window, Qt::Key_Backspace); + QCOMPARE(textChangedSpy.count(), ++textChanges); + QCOMPARE(textEditedSpy.count(), ++textEdits); + + input->clear(); + QCOMPARE(textChangedSpy.count(), ++textChanges); + QCOMPARE(textEditedSpy.count(), textEdits); + + input->setText("TextInput"); + QCOMPARE(textChangedSpy.count(), ++textChanges); + QCOMPARE(textEditedSpy.count(), textEdits); +} + /* TextInput element should only handle left/right keys until the cursor reaches the extent of the text, then they should ignore the keys. -- cgit v1.2.3 From bb123fa3a4b06dabb2a63304ee3d24f94d74c1f2 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 2 Dec 2016 12:08:29 +0100 Subject: add text manual test The initial goal is to verify the behavior of text, preeditText and displayText properties and their associated signals on various platforms. Change-Id: Ie50c78a83930e05158a197f38087db9ae3cba534 Reviewed-by: J-P Nurmi --- tests/manual/text/SignalIndicator.qml | 66 ++++++++++ tests/manual/text/main.cpp | 51 ++++++++ tests/manual/text/main.qml | 56 +++++++++ tests/manual/text/qml.qrc | 7 ++ tests/manual/text/text.pro | 7 ++ .../manual/text/textInputPropertiesAndSignals.qml | 134 +++++++++++++++++++++ 6 files changed, 321 insertions(+) create mode 100644 tests/manual/text/SignalIndicator.qml create mode 100644 tests/manual/text/main.cpp create mode 100644 tests/manual/text/main.qml create mode 100644 tests/manual/text/qml.qrc create mode 100644 tests/manual/text/text.pro create mode 100644 tests/manual/text/textInputPropertiesAndSignals.qml diff --git a/tests/manual/text/SignalIndicator.qml b/tests/manual/text/SignalIndicator.qml new file mode 100644 index 0000000000..3eaadde6d7 --- /dev/null +++ b/tests/manual/text/SignalIndicator.qml @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 + +Rectangle { + implicitWidth: text.implicitWidth * 1.2 + implicitHeight: text.implicitHeight * 1.1 + color: "lightgrey" + property color blipColor: "green" + property int blipDuration: 30 // ms + property alias label: text.text + + function blip() { + blipAnim.start() + } + + SequentialAnimation on color { + id: blipAnim + PropertyAction { value: blipColor } + PauseAnimation { duration: blipDuration } + PropertyAction { value: "lightgrey" } + } + + Text { + id: text + anchors.centerIn: parent + } +} diff --git a/tests/manual/text/main.cpp b/tests/manual/text/main.cpp new file mode 100644 index 0000000000..a4e1060cf5 --- /dev/null +++ b/tests/manual/text/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + + return app.exec(); +} diff --git a/tests/manual/text/main.qml b/tests/manual/text/main.qml new file mode 100644 index 0000000000..d7e214ee38 --- /dev/null +++ b/tests/manual/text/main.qml @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Window 2.2 +import "qrc:/quick/shared/" as Examples + +Window { + width: 800 + height: 600 + visible: true + Examples.LauncherList { + id: ll + anchors.fill: parent + Component.onCompleted: { + addExample("TextInput", "TextInput properties and signals", Qt.resolvedUrl("textInputPropertiesAndSignals.qml")) + } + } +} diff --git a/tests/manual/text/qml.qrc b/tests/manual/text/qml.qrc new file mode 100644 index 0000000000..555e37bd69 --- /dev/null +++ b/tests/manual/text/qml.qrc @@ -0,0 +1,7 @@ + + + main.qml + textInputPropertiesAndSignals.qml + SignalIndicator.qml + + diff --git a/tests/manual/text/text.pro b/tests/manual/text/text.pro new file mode 100644 index 0000000000..3705d41df0 --- /dev/null +++ b/tests/manual/text/text.pro @@ -0,0 +1,7 @@ +TEMPLATE = app + +QT += qml quick + +SOURCES += main.cpp + +RESOURCES += qml.qrc ../../../examples/quick/shared/quick_shared.qrc diff --git a/tests/manual/text/textInputPropertiesAndSignals.qml b/tests/manual/text/textInputPropertiesAndSignals.qml new file mode 100644 index 0000000000..a3fd602c16 --- /dev/null +++ b/tests/manual/text/textInputPropertiesAndSignals.qml @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Layouts 1.1 +import "qrc:/quick/shared/" as Shared + +Item { + width: 600; height: 600 + GridLayout { + columns: 3; rowSpacing: 6; columnSpacing: 6 + anchors { left: parent.left; right: parent.right; top: parent.top; margins: 12 } + + // ---------------------------------------------------- + Text { + text: "try typing and input methods in the TextInput below:" + Layout.columnSpan: 3 + } + + // ---------------------------------------------------- + Text { + text: "TextInput" + } + + Rectangle { + Layout.fillWidth: true + implicitHeight: textInput.implicitHeight + 8 + radius: 4; antialiasing: true + border.color: "black"; color: "transparent" + + TextInput { + id: textInput + anchors.fill: parent; anchors.margins: 4 + + onTextEdited: textEditedInd.blip() + onTextChanged: textChangedInd.blip() + onPreeditTextChanged: preeditInd.blip() + onDisplayTextChanged: displayTextInd.blip() + } + + } + + SignalIndicator { + id: textEditedInd + label: "textEdited" + } + + // ---------------------------------------------------- + Text { text: "text" } + + Text { text: textInput.text; Layout.fillWidth: true } + + SignalIndicator { + id: textChangedInd + label: "textChanged" + } + + // ---------------------------------------------------- + Text { text: "preeditText" } + + Text { text: textInput.preeditText; Layout.fillWidth: true } + + SignalIndicator { + id: preeditInd + label: "preeditTextChanged" + } + + // ---------------------------------------------------- + Text { text: "displayText" } + + Text { text: textInput.displayText; Layout.fillWidth: true } + + SignalIndicator { + id: displayTextInd + label: "displayTextChanged" + } + + // ---------------------------------------------------- + Shared.TextField { + id: copyFrom + Layout.column: 1 + Layout.row: 5 + Layout.fillWidth: true + text: "copy this" + } + + Shared.Button { + Layout.column: 2 + Layout.row: 5 + text: "setText" + onClicked: { + Qt.inputMethod.reset() + textInput.text = copyFrom.text + } + } + } +} -- cgit v1.2.3 From f70066e95e7e23562155686cb7d7874b2d5da5a1 Mon Sep 17 00:00:00 2001 From: Oleg Yadrov Date: Tue, 20 Dec 2016 16:45:20 -0800 Subject: Make it possible to call grabToImage() on Window.contentItem Window.contentItem was not associated with any QQmlContext and QQmlEngine. A valid pointer to QQmlEngine is needed for callback function execution. Task-number: QTBUG-57175 Change-Id: Iab7730bfc8860521ff2e8c1631a11d0e1fe0cf94 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickview.cpp | 2 ++ src/quick/items/qquickwindowmodule.cpp | 3 +++ .../qquickwindow/data/grabContentItemToImage.qml | 15 +++++++++++++++ tests/auto/quick/qquickwindow/qquickwindow.pro | 3 ++- tests/auto/quick/qquickwindow/tst_qquickwindow.cpp | 19 +++++++++++++++++++ 5 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 tests/auto/quick/qquickwindow/data/grabContentItemToImage.qml diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp index 573440ff7f..d7171bf910 100644 --- a/src/quick/items/qquickview.cpp +++ b/src/quick/items/qquickview.cpp @@ -62,6 +62,8 @@ void QQuickViewPrivate::init(QQmlEngine* e) if (engine.isNull()) engine = new QQmlEngine(q); + QQmlEngine::setContextForObject(contentItem, engine.data()->rootContext()); + if (!engine.data()->incubationController()) engine.data()->setIncubationController(q->incubationController()); diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp index ea1fc2f106..42313e4584 100644 --- a/src/quick/items/qquickwindowmodule.cpp +++ b/src/quick/items/qquickwindowmodule.cpp @@ -102,6 +102,9 @@ void QQuickWindowQmlImpl::classBegin() { Q_D(QQuickWindowQmlImpl); QQmlEngine* e = qmlEngine(this); + + QQmlEngine::setContextForObject(contentItem(), e->rootContext()); + //Give QQuickView behavior when created from QML with QQmlApplicationEngine if (QCoreApplication::instance()->property("__qml_using_qqmlapplicationengine") == QVariant(true)) { if (e && !e->incubationController()) diff --git a/tests/auto/quick/qquickwindow/data/grabContentItemToImage.qml b/tests/auto/quick/qquickwindow/data/grabContentItemToImage.qml new file mode 100644 index 0000000000..9086e0cc84 --- /dev/null +++ b/tests/auto/quick/qquickwindow/data/grabContentItemToImage.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 +import QtQuick.Window 2.2 as Window + +Window.Window { + visible: true + width: 100 + height: 100 + property int success: 0 + + function grabContentItemToImage() { + contentItem.grabToImage(function (image) { + success = 1 + }) + } +} diff --git a/tests/auto/quick/qquickwindow/qquickwindow.pro b/tests/auto/quick/qquickwindow/qquickwindow.pro index 05093ba8e0..b0a5f97a32 100644 --- a/tests/auto/quick/qquickwindow/qquickwindow.pro +++ b/tests/auto/quick/qquickwindow/qquickwindow.pro @@ -16,4 +16,5 @@ OTHER_FILES += \ data/AnimationsWhileHidden.qml \ data/Headless.qml \ data/showHideAnimate.qml \ - data/windoworder.qml + data/windoworder.qml \ + data/grabContentItemToImage.qml diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index 300ca392f9..dd00154935 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -370,6 +370,8 @@ private slots: void pointerEventTypeAndPointCount(); + void grabContentItemToImage(); + private: QTouchDevice *touchDevice; QTouchDevice *touchDeviceWithVelocity; @@ -2554,6 +2556,23 @@ void tst_qquickwindow::pointerEventTypeAndPointCount() QVERIFY(!pte.touchPointById(0)); } +void tst_qquickwindow::grabContentItemToImage() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("grabContentItemToImage.qml")); + + QObject *created = component.create(); + QScopedPointer cleanup(created); + QVERIFY(created); + + QQuickWindow *window = qobject_cast(created); + QVERIFY(QTest::qWaitForWindowActive(window)); + + QMetaObject::invokeMethod(window, "grabContentItemToImage"); + QTRY_COMPARE(created->property("success").toInt(), 1); +} + QTEST_MAIN(tst_qquickwindow) #include "tst_qquickwindow.moc" -- cgit v1.2.3 From f43dc181d7416eddfafb7493273a371c1eba8b4a Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 2 Jan 2017 10:46:38 +0100 Subject: Fix QML cache not being invalidated when source path changes When somebody renames the directory name underneath a QML file and its cache file, then we need to re-generate the cache as it contains the fully path of the source path. That is sometimes used to resolve relative URLs (such as images) and therefore needs updating (by re-creating the cache). Task-number: QTBUG-57644 Change-Id: I9766668859aad8e9d71f278c3f26c0585258c14e Reviewed-by: Lars Knoll --- src/qml/compiler/qv4compileddata.cpp | 5 ++ tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp | 58 ++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 8586c84c3d..6aac111897 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -407,6 +407,11 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory const Unit * const oldDataPtr = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data : nullptr; QScopedValueRollback dataPtrChange(data, mappedUnit); + if (sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) { + *errorString = QStringLiteral("QML source file has moved to a different location."); + return false; + } + { const QString foundArchitecture = stringAt(data->architectureIndex); const QString expectedArchitecture = QSysInfo::buildAbi(); diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp index 8af446173d..b265607fd1 100644 --- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp +++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp @@ -53,6 +53,7 @@ private slots: void registerImportForImplicitComponent(); void basicVersionChecks(); void recompileAfterChange(); + void recompileAfterDirectoryChange(); void fileSelectors(); void localAliases(); void cacheResources(); @@ -95,11 +96,17 @@ struct TestCompiler TestCompiler(QQmlEngine *engine) : engine(engine) , tempDir() - , testFilePath(tempDir.path() + QStringLiteral("/test.qml")) - , cacheFilePath(tempDir.path() + QStringLiteral("/test.qmlc")) - , mappedFile(cacheFilePath) , currentMapping(nullptr) { + init(tempDir.path()); + } + + void init(const QString &baseDirectory) + { + closeMapping(); + testFilePath = baseDirectory + QStringLiteral("/test.qml"); + cacheFilePath = baseDirectory + QStringLiteral("/test.qmlc"); + mappedFile.setFileName(cacheFilePath); } bool compile(const QByteArray &contents) @@ -187,8 +194,8 @@ struct TestCompiler QQmlEngine *engine; const QTemporaryDir tempDir; - const QString testFilePath; - const QString cacheFilePath; + QString testFilePath; + QString cacheFilePath; QString lastErrorString; QFile mappedFile; uchar *currentMapping; @@ -441,6 +448,47 @@ void tst_qmldiskcache::recompileAfterChange() } } +void tst_qmldiskcache::recompileAfterDirectoryChange() +{ + QQmlEngine engine; + TestCompiler testCompiler(&engine); + + QVERIFY(testCompiler.tempDir.isValid()); + + QVERIFY(QDir(testCompiler.tempDir.path()).mkdir("source1")); + testCompiler.init(testCompiler.tempDir.path() + QLatin1String("/source1")); + + { + const QByteArray contents = QByteArrayLiteral("import QtQml 2.0\n" + "QtObject {\n" + " property int blah: 42;\n" + "}"); + + testCompiler.clearCache(); + QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString)); + QVERIFY2(testCompiler.verify(), qPrintable(testCompiler.lastErrorString)); + testCompiler.closeMapping(); + } + + const QDateTime initialCacheTimeStamp = QFileInfo(testCompiler.cacheFilePath).lastModified(); + + QDir(testCompiler.tempDir.path()).rename(QStringLiteral("source1"), QStringLiteral("source2")); + waitForFileSystem(); + + testCompiler.init(testCompiler.tempDir.path() + QLatin1String("/source2")); + + { + CleanlyLoadingComponent component(&engine, testCompiler.testFilePath); + QScopedPointer obj(component.create()); + QVERIFY(!obj.isNull()); + QCOMPARE(obj->property("blah").toInt(), 42); + } + + QFile cacheFile(testCompiler.cacheFilePath); + QVERIFY2(cacheFile.exists(), qPrintable(cacheFile.fileName())); + QVERIFY(QFileInfo(testCompiler.cacheFilePath).lastModified() > initialCacheTimeStamp); +} + void tst_qmldiskcache::fileSelectors() { QQmlEngine engine; -- cgit v1.2.3 From 9b2b06fd7bf07e1012b47798f38ba881e693436f Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 2 Jan 2017 14:04:48 +0100 Subject: qml: use QUrl::fromUserInput("file.qml", QDir::currentPath()) After change dc6b73390b262b9554599cbf40539763b1280261 in qtbase, the qml runtime was failing at an assertion in QQmlTypeLoader::getType() which tries to avoid relative URLs and relative directory paths. It's important to convert relative paths to fully-qualified paths when converting to an URL, because QQmlTypeLoader uses it as a cache key, and we want to avoid ambiguity about which file is being cached. Task-number: QTBUG-57870 Change-Id: Ib984cf722009f5f04cb67fffbc52d12bcc98df89 Reviewed-by: David Faure Reviewed-by: Robin Burchell --- tools/qml/main.cpp | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp index 5e8b872821..e8a506264c 100644 --- a/tools/qml/main.cpp +++ b/tools/qml/main.cpp @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include @@ -568,29 +567,14 @@ int main(int argc, char *argv[]) loadDummyDataFiles(e, dummyDir); for (const QString &path : qAsConst(files)) { - //QUrl::fromUserInput doesn't treat no scheme as relative file paths -#if QT_CONFIG(regularexpression) - QRegularExpression urlRe("[[:word:]]+://.*"); - if (urlRe.match(path).hasMatch()) { //Treat as a URL - QUrl url = QUrl::fromUserInput(path); - if (verboseMode) - printf("qml: loading %s\n", - qPrintable(url.isLocalFile() - ? QDir::toNativeSeparators(url.toLocalFile()) - : url.toString())); + QUrl url = QUrl::fromUserInput(path, QDir::currentPath()); + if (verboseMode) + printf("qml: loading %s\n", qPrintable(url.toString())); + QByteArray strippedFile; + if (getFileSansBangLine(path, strippedFile)) + e.loadData(strippedFile, e.baseUrl().resolved(url)); //QQmlComponent won't resolve it for us, it doesn't know it's a valid file if we loadData + else //Errors or no bang line e.load(url); - } else -#endif - { //Local file path - if (verboseMode) - printf("qml: loading %s\n", qPrintable(QDir::toNativeSeparators(path))); - - QByteArray strippedFile; - if (getFileSansBangLine(path, strippedFile)) - e.loadData(strippedFile, e.baseUrl().resolved(QUrl::fromLocalFile(path))); //QQmlComponent won't resolve it for us, it doesn't know it's a valid file if we loadData - else //Errors or no bang line - e.load(path); - } } if (lw->earlyExit) -- cgit v1.2.3 From fc724dd473cd68fd074ed5f7d849a0b23f99ebd4 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 3 Jan 2017 13:26:24 +0100 Subject: Bump version Change-Id: I26e2b01ac6ce30b04509af1413163460e992cb92 --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index 556f554e5e..9d7f045e45 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,4 +1,4 @@ load(qt_build_config) CONFIG += warning_clean -MODULE_VERSION = 5.8.0 +MODULE_VERSION = 5.8.1 -- cgit v1.2.3 From 4406667874b22803ef78650f4af28337eaf7952b Mon Sep 17 00:00:00 2001 From: Kavindra Palaraja Date: Wed, 28 Dec 2016 12:06:29 +0100 Subject: Added the missing link to Animation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Animator inherits from QQuickAbstractAnimation which is known as Animation in QML. Its properties are inherited. Task-number: QTBUG-55738 Change-Id: If16c87c9367825d7661940e7c1930179862e59cb Reviewed-by: Mitch Curtis Reviewed-by: Topi Reiniö --- src/quick/util/qquickanimator.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/quick/util/qquickanimator.cpp b/src/quick/util/qquickanimator.cpp index 5d2af0f940..c3b5865369 100644 --- a/src/quick/util/qquickanimator.cpp +++ b/src/quick/util/qquickanimator.cpp @@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE \inqmlmodule QtQuick \since 5.2 \ingroup qtquick-transitions-animations + \inherits Animation \brief Is the base of all QML animators. Animator types are a special type of animation which operate -- cgit v1.2.3 From 63a03f6772b8c008c3b7e6d17e484f585244a5e7 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 30 Dec 2016 12:31:44 +0100 Subject: mpta-crosshairs manual test: correct the velocity vector rotation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit acos cannot return any possible angle, but atan2 can. Change-Id: Ic277bc1d3616900775b6076dce6b05bdf3c35da3 Reviewed-by: Jan Arve Sæther --- tests/manual/touch/mpta-crosshairs.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/manual/touch/mpta-crosshairs.qml b/tests/manual/touch/mpta-crosshairs.qml index 8b71e4fdc3..a55dfc7799 100644 --- a/tests/manual/touch/mpta-crosshairs.qml +++ b/tests/manual/touch/mpta-crosshairs.qml @@ -98,7 +98,8 @@ Rectangle { height: 1 x: touchPoint.x y: touchPoint.y - rotation: width > 0 ? Math.acos(touchPoint.velocity.x / width) : 0 + rotation: width > 0 ? Math.atan2(touchPoint.velocity.y, touchPoint.velocity.x) * 180 / Math.PI : 0 + Behavior on rotation { SmoothedAnimation { duration: 20 } } transformOrigin: Item.BottomLeft } -- cgit v1.2.3 From 4038160a32dcb51d843fb751a9a9340e7cc2bb63 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 14 Mar 2016 17:37:36 +0100 Subject: MultiPointTouchArea.TouchPoint: add rotation, uniqueId and ellipseDiameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far uniqueId and rotation are mainly applicable to TUIO. Deprecate the area property in favor of ellipseDiameters. Also improve the mpta-crosshairs manual test to show this information. Change-Id: I16ea6618ae21ce66dac45638d6e2bb3c0a3b1818 Reviewed-by: Jan Arve Sæther --- src/quick/doc/images/touchpoint-metrics.png | Bin 0 -> 38894 bytes src/quick/items/qquickitemsmodule.cpp | 3 + src/quick/items/qquickmultipointtoucharea.cpp | 73 +++++++++++++++++++++- src/quick/items/qquickmultipointtoucharea_p.h | 19 ++++++ tests/manual/touch/mpta-crosshairs.qml | 84 +++++++++++++++++++------- 5 files changed, 156 insertions(+), 23 deletions(-) create mode 100644 src/quick/doc/images/touchpoint-metrics.png diff --git a/src/quick/doc/images/touchpoint-metrics.png b/src/quick/doc/images/touchpoint-metrics.png new file mode 100644 index 0000000000..9b0bf22e25 Binary files /dev/null and b/src/quick/doc/images/touchpoint-metrics.png differ diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index ee7b566266..0b325d7fa8 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -377,6 +377,9 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType(uri, 2, 9, "Flickable"); qmlRegisterType(uri, 2, 9, "MouseArea"); qmlRegisterType(uri, 2, 9, "TextInput"); + qmlRegisterType(uri, 2, 9, "TouchPoint"); + qRegisterMetaType("QPointingDeviceUniqueId"); + qmlRegisterUncreatableType(uri, 2, 9, "PointingDeviceUniqueId", QQuickTouchPoint::tr("PointingDeviceUniqueId is only available via read-only properties")); } static void initResources() diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp index 706980cd13..62119effb2 100644 --- a/src/quick/items/qquickmultipointtoucharea.cpp +++ b/src/quick/items/qquickmultipointtoucharea.cpp @@ -60,6 +60,8 @@ DEFINE_BOOL_CONFIG_OPTION(qmlVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING) The TouchPoint type contains information about a touch point, such as the current position, pressure, and area. + + \image touchpoint-metrics.png */ /*! @@ -100,17 +102,30 @@ void QQuickTouchPoint::setY(qreal y) emit yChanged(); } +/*! + \qmlproperty size QtQuick::TouchPoint::ellipseDiameters + \since 5.9 + + This property holds the major and minor axes of the ellipse representing + the covered area of the touch point. +*/ +void QQuickTouchPoint::setEllipseDiameters(const QSizeF &d) +{ + if (_ellipseDiameters == d) + return; + _ellipseDiameters = d; + emit ellipseDiametersChanged(); +} + /*! \qmlproperty real QtQuick::TouchPoint::pressure \qmlproperty vector2d QtQuick::TouchPoint::velocity - \qmlproperty rectangle QtQuick::TouchPoint::area These properties hold additional information about the current state of the touch point. \list \li \c pressure is a value in the range of 0.0 to 1.0. \li \c velocity is a vector with magnitude reported in pixels per second. - \li \c area is a rectangle covering the area of the touch point, centered on the current position of the touch point. \endlist Not all touch devices support velocity. If velocity is not supported, it will be reported @@ -124,6 +139,26 @@ void QQuickTouchPoint::setPressure(qreal pressure) emit pressureChanged(); } +/*! + \qmlproperty real QtQuick::TouchPoint::rotation + \since 5.9 + + This property holds the angular orientation of this touch point. The return + value is in degrees, where zero (the default) indicates the finger or token + is pointing upwards, a negative angle means it's rotated to the left, and a + positive angle means it's rotated to the right. Most touchscreens do not + detect rotation, so zero is the most common value. + + \sa QTouchEvent::TouchPoint::rotation() +*/ +void QQuickTouchPoint::setRotation(qreal r) +{ + if (_rotation == r) + return; + _rotation = r; + emit rotationChanged(); +} + void QQuickTouchPoint::setVelocity(const QVector2D &velocity) { if (_velocity == velocity) @@ -132,6 +167,18 @@ void QQuickTouchPoint::setVelocity(const QVector2D &velocity) emit velocityChanged(); } +/*! + \deprecated + \qmlproperty rectangle QtQuick::TouchPoint::area + + A rectangle covering the area of the touch point, centered on the current + position of the touch point. + + It is deprecated because a touch point is more correctly modeled as an ellipse, + whereas this rectangle represents the outer bounds of the ellipse after \l rotation. + + \sa horizontalDiameter, verticalDiameter +*/ void QQuickTouchPoint::setArea(const QRectF &area) { if (_area == area) @@ -221,6 +268,25 @@ void QQuickTouchPoint::setSceneY(qreal sceneY) emit sceneYChanged(); } +/*! + \qmlproperty PointingDeviceUniqueId QtQuick::TouchPoint::uniqueId + \since 5.9 + + This property holds the unique ID of the touch point or token. + + It is normally empty, because touchscreens cannot uniquely identify fingers. + But when it is set, it is expected to uniquely identify a specific token + (fiducial object). + + Interpreting the contents of this ID requires knowledge of the hardware and + drivers in use (e.g. various TUIO-based touch surfaces). +*/ +void QQuickTouchPoint::setUniqueId(const QPointingDeviceUniqueId &id) +{ + _uniqueId = id; + emit uniqueIdChanged(); +} + /*! \qmltype MultiPointTouchArea \instantiates QQuickMultiPointTouchArea @@ -691,9 +757,12 @@ void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp, const QT { //TODO: if !qmlDefined, could bypass setters. // also, should only emit signals after all values have been set + dtp->setUniqueId(p->uniqueId()); dtp->setX(p->pos().x()); dtp->setY(p->pos().y()); + dtp->setEllipseDiameters(p->ellipseDiameters()); dtp->setPressure(p->pressure()); + dtp->setRotation(p->rotation()); dtp->setVelocity(p->velocity()); dtp->setArea(p->rect()); dtp->setStartX(p->startPos().x()); diff --git a/src/quick/items/qquickmultipointtoucharea_p.h b/src/quick/items/qquickmultipointtoucharea_p.h index 541eb04764..25e1056712 100644 --- a/src/quick/items/qquickmultipointtoucharea_p.h +++ b/src/quick/items/qquickmultipointtoucharea_p.h @@ -67,10 +67,13 @@ class Q_AUTOTEST_EXPORT QQuickTouchPoint : public QObject { Q_OBJECT Q_PROPERTY(int pointId READ pointId NOTIFY pointIdChanged) + Q_PROPERTY(QPointingDeviceUniqueId uniqueId READ uniqueId NOTIFY uniqueIdChanged REVISION 9) Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged) Q_PROPERTY(qreal x READ x NOTIFY xChanged) Q_PROPERTY(qreal y READ y NOTIFY yChanged) + Q_PROPERTY(QSizeF ellipseDiameters READ ellipseDiameters NOTIFY ellipseDiametersChanged REVISION 9) Q_PROPERTY(qreal pressure READ pressure NOTIFY pressureChanged) + Q_PROPERTY(qreal rotation READ rotation NOTIFY rotationChanged REVISION 9) Q_PROPERTY(QVector2D velocity READ velocity NOTIFY velocityChanged) Q_PROPERTY(QRectF area READ area NOTIFY areaChanged) @@ -86,6 +89,7 @@ public: : _id(0), _x(0.0), _y(0.0), _pressure(0.0), + _rotation(0), _qmlDefined(qmlDefined), _inUse(false), _pressed(false), @@ -97,15 +101,24 @@ public: int pointId() const { return _id; } void setPointId(int id); + QPointingDeviceUniqueId uniqueId() const { return _uniqueId; } + void setUniqueId(const QPointingDeviceUniqueId &id); + qreal x() const { return _x; } void setX(qreal x); qreal y() const { return _y; } void setY(qreal y); + QSizeF ellipseDiameters() const { return _ellipseDiameters; } + void setEllipseDiameters(const QSizeF &d); + qreal pressure() const { return _pressure; } void setPressure(qreal pressure); + qreal rotation() const { return _rotation; } + void setRotation(qreal r); + QVector2D velocity() const { return _velocity; } void setVelocity(const QVector2D &velocity); @@ -141,9 +154,12 @@ public: Q_SIGNALS: void pressedChanged(); void pointIdChanged(); + Q_REVISION(9) void uniqueIdChanged(); void xChanged(); void yChanged(); + Q_REVISION(9) void ellipseDiametersChanged(); void pressureChanged(); + Q_REVISION(9) void rotationChanged(); void velocityChanged(); void areaChanged(); void startXChanged(); @@ -159,6 +175,8 @@ private: qreal _x; qreal _y; qreal _pressure; + qreal _rotation; + QSizeF _ellipseDiameters; QVector2D _velocity; QRectF _area; bool _qmlDefined; @@ -170,6 +188,7 @@ private: qreal _previousY; qreal _sceneX; qreal _sceneY; + QPointingDeviceUniqueId _uniqueId; }; class QQuickGrabGestureEvent : public QObject diff --git a/tests/manual/touch/mpta-crosshairs.qml b/tests/manual/touch/mpta-crosshairs.qml index a55dfc7799..d1dbd0f188 100644 --- a/tests/manual/touch/mpta-crosshairs.qml +++ b/tests/manual/touch/mpta-crosshairs.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the manual tests of the Qt Toolkit. @@ -38,11 +38,13 @@ ** ****************************************************************************/ -import QtQuick 2.4 +import QtQuick 2.9 import QtQuick.Window 2.2 Rectangle { id: root + width: 480 + height: 480 color: "black" MultiPointTouchArea { @@ -51,11 +53,11 @@ Rectangle { touchPoints: [ TouchPoint { property color color: "red" }, TouchPoint { property color color: "orange" }, - TouchPoint { property color color: "yellow" }, + TouchPoint { property color color: "lightsteelblue" }, TouchPoint { property color color: "green" }, TouchPoint { property color color: "blue" }, TouchPoint { property color color: "violet" }, - TouchPoint { property color color: "cyan" }, + TouchPoint { property color color: "steelblue" }, TouchPoint { property color color: "magenta" }, TouchPoint { property color color: "goldenrod" }, TouchPoint { property color color: "darkgray" } @@ -65,40 +67,80 @@ Rectangle { model: 10 Item { - anchors.fill: parent + id: crosshairs property TouchPoint touchPoint + x: touchPoint.x - width / 2 + y: touchPoint.y - height / 2 + width: 300; height: 300 visible: touchPoint.pressed + rotation: touchPoint.rotation Rectangle { color: touchPoint.color - anchors.top: parent.top - anchors.bottom: parent.bottom - width: 2 - x: touchPoint.x - 1 + anchors.centerIn: parent + width: 2; height: parent.height + antialiasing: true } Rectangle { color: touchPoint.color - anchors.left: parent.left - anchors.right: parent.right - height: 2 - y: touchPoint.y - 1 + anchors.centerIn: parent + width: parent.width; height: 2 + antialiasing: true } Rectangle { color: touchPoint.color - width: 50 * touchPoint.pressure - height: width + implicitWidth: label.implicitWidth + 8 + implicitHeight: label.implicitHeight + 16 radius: width / 2 - x: touchPoint.x - width / 2 - y: touchPoint.y - width / 2 + anchors.centerIn: parent + antialiasing: true + Rectangle { + color: "black" + opacity: 0.35 + width: (parent.width - 8) * touchPoint.pressure + height: width + radius: width / 2 + anchors.centerIn: parent + antialiasing: true + } + Rectangle { + color: "transparent" + border.color: "white" + border.width: 2 + opacity: 0.75 + visible: width > 0 + width: touchPoint.ellipseDiameters.width + height: touchPoint.ellipseDiameters.height + radius: Math.min(width, height) / 2 + anchors.centerIn: parent + antialiasing: true + } + Text { + id: label + anchors.centerIn: parent + color: "white" + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + property string uid: touchPoint.uniqueId === undefined || touchPoint.uniqueId.numericId === -1 ? + "" : "\nUID " + touchPoint.uniqueId.numericId + text: "x " + touchPoint.x.toFixed(1) + + "\ny " + touchPoint.y.toFixed(1) + uid + + "\nID " + touchPoint.pointId.toString(16) + + "\n∡" + touchPoint.rotation.toFixed(1) + "°" + } } Rectangle { id: velocityVector visible: width > 0 width: touchPoint.velocity.length() - height: 1 - x: touchPoint.x - y: touchPoint.y - rotation: width > 0 ? Math.atan2(touchPoint.velocity.y, touchPoint.velocity.x) * 180 / Math.PI : 0 + height: 4 + Behavior on width { SmoothedAnimation { duration: 200 } } + radius: height / 2 + antialiasing: true + color: "gray" + x: crosshairs.width / 2 + y: crosshairs.height / 2 + rotation: width > 0 ? Math.atan2(touchPoint.velocity.y, touchPoint.velocity.x) * 180 / Math.PI - crosshairs.rotation : 0 Behavior on rotation { SmoothedAnimation { duration: 20 } } transformOrigin: Item.BottomLeft } -- cgit v1.2.3 From 0a88774a0f11bf96a87012ac4a83e31ced19460b Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 22 Dec 2016 15:05:56 +0100 Subject: Fix stencil clips with core profile contexts Client-side pointers are not supported. Start using a VBO instead. Task-number: QTBUG-57768 Change-Id: Ia7ac9b0838d837b02e8bf99fcd22f0373cb357c9 Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 6db96f369c..4893c175a3 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -2022,6 +2022,8 @@ Renderer::ClipType Renderer::updateStencilClip(const QSGClipNode *clip) } ClipType clipType = NoClip; + GLuint vbo = 0; + int vboSize = 0; glDisable(GL_SCISSOR_TEST); @@ -2106,7 +2108,21 @@ Renderer::ClipType Renderer::updateStencilClip(const QSGClipNode *clip) const QSGGeometry *g = clip->geometry(); Q_ASSERT(g->attributeCount() > 0); const QSGGeometry::Attribute *a = g->attributes(); - glVertexAttribPointer(0, a->tupleSize, a->type, GL_FALSE, g->sizeOfVertex(), g->vertexData()); + + if (!vbo) + glGenBuffers(1, &vbo); + + glBindBuffer(GL_ARRAY_BUFFER, vbo); + + const int vertexByteSize = g->sizeOfVertex() * g->vertexCount(); + if (vboSize < vertexByteSize) { + vboSize = vertexByteSize; + glBufferData(GL_ARRAY_BUFFER, vertexByteSize, g->vertexData(), GL_STATIC_DRAW); + } else { + glBufferSubData(GL_ARRAY_BUFFER, 0, vertexByteSize, g->vertexData()); + } + + glVertexAttribPointer(0, a->tupleSize, a->type, GL_FALSE, g->sizeOfVertex(), 0); m_clipProgram.setUniformValue(m_clipMatrixId, m); if (g->indexCount()) { @@ -2115,12 +2131,17 @@ Renderer::ClipType Renderer::updateStencilClip(const QSGClipNode *clip) glDrawArrays(g->drawingMode(), 0, g->vertexCount()); } + glBindBuffer(GL_ARRAY_BUFFER, 0); + ++m_currentStencilValue; } clip = clip->clipList(); } + if (vbo) + glDeleteBuffers(1, &vbo); + if (clipType & StencilClip) { m_clipProgram.disableAttributeArray(0); glStencilFunc(GL_EQUAL, m_currentStencilValue, 0xff); // stencil test, ref, test mask -- cgit v1.2.3 From 0fada59c49a06cec8bfca72eb86ad340967b6f26 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 3 Jan 2017 15:58:12 +0100 Subject: Clarify JIT selection for 32-bit and 64-bit architectures Instead of relying on the somewhat "cryptic" ILP32 macro on x86/x86-64, we can also use the macro that the JIT generated code _really_ relies on, which is the size of pointers. For x32 those will be 4 despite Q_PROCESSOR_X86_64, and the JIT will end up disabled. For regular x86 and x86-64 it should get enabled. The same logic is applied to ARM32/ARM64 to disable the JIT once machines start showing up with ILP32 data model on ARM64. Change-Id: Id8dfb203c9b75e8ed5a61dcae28482f8f99be75f Reviewed-by: Thiago Macieira Reviewed-by: Dmitry Shachnev --- src/qml/jsruntime/qv4global_p.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index c37ad1668d..1dbc538be2 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -97,19 +97,19 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); } // // NOTE: This should match the logic in qv4targetplatform_p.h! -#if defined(Q_PROCESSOR_X86) && !defined(__ILP32__) \ +#if defined(Q_PROCESSOR_X86) && (QT_POINTER_SIZE == 4) \ && (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD)) # define V4_ENABLE_JIT -#elif defined(Q_PROCESSOR_X86_64) && !defined(__ILP32__) \ +#elif defined(Q_PROCESSOR_X86_64) && (QT_POINTER_SIZE == 8) \ && (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_FREEBSD)) # define V4_ENABLE_JIT -#elif defined(Q_PROCESSOR_ARM_32) +#elif defined(Q_PROCESSOR_ARM_32) && (QT_POINTER_SIZE == 4) # if defined(thumb2) || defined(__thumb2__) || ((defined(__thumb) || defined(__thumb__)) && __TARGET_ARCH_THUMB-0 == 4) # define V4_ENABLE_JIT # elif defined(__ARM_ARCH_ISA_THUMB) && __ARM_ARCH_ISA_THUMB == 2 // clang 3.5 and later will set this if the core supports the Thumb-2 ISA. # define V4_ENABLE_JIT # endif -#elif defined(Q_PROCESSOR_ARM_64) +#elif defined(Q_PROCESSOR_ARM_64) && (QT_POINTER_SIZE == 8) # if defined(Q_OS_LINUX) # define V4_ENABLE_JIT # endif -- cgit v1.2.3 From 0d2db1438e3f7e07f768991a39d4f6b2ab1dc432 Mon Sep 17 00:00:00 2001 From: Kavindra Palaraja Date: Wed, 28 Dec 2016 20:40:28 +0100 Subject: Added documentation for the GroupSwitchModifier Used the default sentence from Qt::KeyboardModifier. Task-number: QTBUG-53211 Change-Id: If763ca1b8d9ee7dcfa511f3a19dd012aac4d4f9c Reviewed-by: Robin Burchell --- src/quick/items/qquickevents.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index a5497f4627..70d95ccdf8 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -137,6 +137,7 @@ Item { \li Qt.AltModifier - An Alt key on the keyboard is pressed. \li Qt.MetaModifier - A Meta key on the keyboard is pressed. \li Qt.KeypadModifier - A keypad button is pressed. + \li Qt.GroupSwitchModifier - X11 only. A Mode_switch key on the keyboard is pressed. \endlist For example, to react to a Shift key + Enter key combination: -- cgit v1.2.3 From e62fde84e2fac321386c6fbb6fb90a36c0989a3d Mon Sep 17 00:00:00 2001 From: Kavindra Palaraja Date: Wed, 28 Dec 2016 21:52:24 +0100 Subject: Clarified that QQmlListProperty can only be used for lists of QObject-derived object pointers Added the info to the QQmlListProperty's brief itself so it stands out. Removed the original note. Also added a See also link to the complete example. Task-number: QTBUG-37888 Change-Id: I9e1b77b035321ade44fe57d56e68a9c3d20cb879 Reviewed-by: Mitch Curtis --- src/qml/qml/qqmllist.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp index a719956483..edd93ef03d 100644 --- a/src/qml/qml/qqmllist.cpp +++ b/src/qml/qml/qqmllist.cpp @@ -335,7 +335,7 @@ int QQmlListReference::count() const \since 5.0 \inmodule QtQml \brief The QQmlListProperty class allows applications to expose list-like -properties to QML. +properties of QObject-derived classes to QML. QML has many list properties, where more than one object value can be assigned. The use of a list property from QML looks like this: @@ -369,7 +369,8 @@ QML list properties are type-safe - in this case \c {Fruit} is a QObject type th The \l {Qt Quick 1} version of this class is named QDeclarativeListProperty. -\note QQmlListProperty can only be used for lists of QObject-derived object pointers. +\sa {Extending QML - Object and List Property Types Example} + */ /*! -- cgit v1.2.3 From 321726cb5e87be1969f22a0eef4166ba36344329 Mon Sep 17 00:00:00 2001 From: Jacques GUILLOU Date: Wed, 4 Jan 2017 14:31:29 +0100 Subject: qmlplugindump : Add a "-output" argument to specify the output file Having only the possibility to redirect the stdout of qmlplugindump to a file is both unconvenient and unreliable since some plugins might write content (such as logs) to stdout, which pollute the output. Change-Id: I8b1d482d7674945e6145d59aea839c54600e7784 Reviewed-by: Marco Benelli --- tools/qmlplugindump/main.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp index 883afa057c..443ede4bf0 100644 --- a/tools/qmlplugindump/main.cpp +++ b/tools/qmlplugindump/main.cpp @@ -739,7 +739,7 @@ void sigSegvHandler(int) { void printUsage(const QString &appName) { std::cerr << qPrintable(QString( - "Usage: %1 [-v] [-noinstantiate] [-defaultplatform] [-[non]relocatable] [-dependencies ] [-merge ] [-noforceqtquick] module.uri version [module/import/path]\n" + "Usage: %1 [-v] [-noinstantiate] [-defaultplatform] [-[non]relocatable] [-dependencies ] [-merge ] [-output ] [-noforceqtquick] module.uri version [module/import/path]\n" " %1 [-v] [-noinstantiate] -path path/to/qmldir/directory [version]\n" " %1 [-v] -builtins\n" "Example: %1 Qt.labs.folderlistmodel 2.0 /home/user/dev/qt-install/imports").arg( @@ -994,6 +994,7 @@ int main(int argc, char *argv[]) return EXIT_INVALIDARGUMENTS; } + QString outputFilename; QString pluginImportUri; QString pluginImportVersion; bool relocatable = true; @@ -1047,6 +1048,13 @@ int main(int argc, char *argv[]) } else if (arg == QLatin1String("--noforceqtquick") || arg == QLatin1String("-noforceqtquick")){ forceQtQuickDependency = false; + } else if (arg == QLatin1String("--output") + || arg == QLatin1String("-output")) { + if (++iArg == args.size()) { + std::cerr << "missing output file" << std::endl; + return EXIT_INVALIDARGUMENTS; + } + outputFilename = args.at(iArg); } else if (arg == QLatin1String("--defaultplatform") || arg == QLatin1String("-defaultplatform")) { continue; @@ -1300,7 +1308,15 @@ int main(int argc, char *argv[]) qml.writeEndObject(); qml.writeEndDocument(); - std::cout << bytes.constData() << std::flush; + if (!outputFilename.isEmpty()) { + QFile file(outputFilename); + if (file.open(QIODevice::WriteOnly)) { + QTextStream stream(&file); + stream << bytes.constData(); + } + } else { + std::cout << bytes.constData() << std::flush; + } // workaround to avoid crashes on exit QTimer timer; -- cgit v1.2.3 From fffb997e192a72b4dcd66edc2fbad5473dd359f3 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 6 Jan 2017 09:22:27 +0100 Subject: Fix incorrect JavaScript evaluation with the JIT This is a regression from commit 7e14b531b294650733a61a9365eb9ef74f8a7a90, that replaced a QHash with a vector of intervals. When an interval is split, it may happen that during one interval a temp is stored in a register and in the second interval it ends up in a different register or the stack. The _liveIntervals variable, formerly the _intervalForTemp hash, tracked the intervals per temp when going through the basic blocks and statements during the renumbering phase. Indexing uniquely by temp is important therefore for _liveIntervals and addNewIntervals violated that by replacing the QHash replacement _intervalForTemp[i->temp()] = i; with _liveIntervals.push_back(i); This is how we may end up with multiple intervals for the same temp (in different locations), and when doing the linear lookup we'd only find the first. Restoring the replacement behavior and thus ensuring uniqueness by temp fixes the miscompilations. Task-number: QTBUG-57779 Change-Id: Ib8f53672b66750f68e16e47794dbc5f39989e1a2 Reviewed-by: Lars Knoll Reviewed-by: Robin Burchell --- src/qml/jit/qv4regalloc.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index 406b9096ea..b168a1e2ba 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -969,7 +969,15 @@ private: break; Q_ASSERT(!i->isFixedInterval()); - _liveIntervals.push_back(i); + auto it = _liveIntervals.begin(); + for (; it != _liveIntervals.end(); ++it) { + if ((*it)->temp() == i->temp()) { + *it = i; + break; + } + } + if (it == _liveIntervals.end()) + _liveIntervals.push_back(i); // qDebug() << "-- Activating interval for temp" << i->temp().index; _unprocessedReverseOrder.removeLast(); -- cgit v1.2.3 From 11aef4eec22cac62d7728ee2895efe4cc80cd335 Mon Sep 17 00:00:00 2001 From: Kavindra Palaraja Date: Wed, 28 Dec 2016 21:22:13 +0100 Subject: Clarify MouseArea's onClicked and onPressAndHold documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changing the accepted property within the onClicked and onPressAndHold event handlers only have an effect if the propagateComposedEvents property is true. Task-number: QTBUG-46912 Change-Id: I66a9114f6dafdf79a5fbf1278656c2988ffb42a2 Reviewed-by: Tor Arne Vestbø --- src/quick/items/qquickmousearea.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index 5e30bf9e0a..3160495332 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -340,7 +340,7 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i position of the release of the click, and whether the click was held. When handling this signal, changing the \l {MouseEvent::}{accepted} property of the \a mouse - parameter has no effect. + parameter has no effect, unless the \l propagateComposedEvents property is \c true. The corresponding handler is \c onClicked. */ @@ -384,7 +384,7 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i position of the press, and which button is pressed. When handling this signal, changing the \l {MouseEvent::}{accepted} property of the \a mouse - parameter has no effect. + parameter has no effect, unless the \l propagateComposedEvents property is \c true. The corresponding handler is \c onPressAndHold. */ -- cgit v1.2.3 From 27ea28b0f451076e773f9dc78babfdd799c3e0d8 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Fri, 16 Dec 2016 13:14:01 +0100 Subject: Doc: Rearranged order of Extending QML Examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rearranged in logical order of example build up Change-Id: I6af8e39bd900d4ce058de46e0b3ebd5e368222c8 Reviewed-by: Topi Reiniö --- examples/qml/doc/src/qml-extending.qdoc | 19 ++++++++++--- examples/qml/referenceexamples/extended/main.cpp | 4 +++ src/qml/doc/src/examples.qdoc | 36 ++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/examples/qml/doc/src/qml-extending.qdoc b/examples/qml/doc/src/qml-extending.qdoc index 0812a3dba1..0cb004be7d 100644 --- a/examples/qml/doc/src/qml-extending.qdoc +++ b/examples/qml/doc/src/qml-extending.qdoc @@ -75,9 +75,21 @@ This example builds on: Shows how to use \l {QQmlEngine::}{qmlRegisterExtendedType()} to provide an \l {Registering Extension Objects}{extension object} to a \l QLineEdit without modifying or -subclassing. The QML engine instantiates a \l QLineEdit and sets a property that -only exists on the extension type. The extension type performs calls on the \l -QLineEdit that otherwise will not be accessible to the QML engine. +subclassing. + +\snippet referenceexamples/extended/main.cpp 0 + +The QML engine instantiates a \l QLineEdit + +\snippet referenceexamples/extended/main.cpp 1 + +and sets a property that oly exists on the extension type. + +\snippet referenceexamples/extended/example.qml 0 + +The QML engine instantiates a \l QLineEdit and sets a property that +only exists on the extension type. The extension type performs calls on the +\l QLineEdit that otherwise will not be accessible to the QML engine. */ @@ -293,7 +305,6 @@ This example builds on: This example builds on: \list -\li \l {Extending QML - Default Property Example} \li \l {Extending QML - Inheritance and Coercion Example} \li \l {Extending QML - Object and List Property Types Example} \li \l {Extending QML - Adding Types Example} diff --git a/examples/qml/referenceexamples/extended/main.cpp b/examples/qml/referenceexamples/extended/main.cpp index fc11587841..f72cb0d9e2 100644 --- a/examples/qml/referenceexamples/extended/main.cpp +++ b/examples/qml/referenceexamples/extended/main.cpp @@ -48,11 +48,15 @@ int main(int argc, char ** argv) { QApplication app(argc, argv); +// ![0] qmlRegisterExtendedType("People", 1,0, "QLineEdit"); +// ![0] +// ![1] QQmlEngine engine; QQmlComponent component(&engine, QUrl("qrc:example.qml")); QLineEdit *edit = qobject_cast(component.create()); +// ![1] if (edit) { edit->show(); diff --git a/src/qml/doc/src/examples.qdoc b/src/qml/doc/src/examples.qdoc index f3550ae199..4f12d42f48 100644 --- a/src/qml/doc/src/examples.qdoc +++ b/src/qml/doc/src/examples.qdoc @@ -32,4 +32,40 @@ The list of examples demonstrating how to extend C++ to QML or the other way around. + +\noautolist + +\table + \row + \li \l {Extending QML - Adding Types Example} + \li Exporting C++ Classes + \row + \li \l {Extending QML - Object and List Property Types Example} + \li Exporting C++ Properties + \row + \li \l {Extending QML - Extension Objects Example} + \li Extension Objects + \row + \li \l {Extending QML - Inheritance and Coercion Example} + \li C++ Inheritance and Coercion + \row + \li \l {Extending QML - Methods Example} + \li Methods Support + \row + \li \l {Extending QML - Attached Properties Example} + \li Attached Properties + \row + \li \l {Extending QML - Signal Support Example} + \li Signal Support + \row + \li \l {Extending QML - Property Value Source Example} + \li Property Value Source + \row + \li \l {Extending QML - Default Property Example} + \li Default Property + \row + \li \l {Extending QML - Grouped Properties Example} + \li Grouped Properties +\endtable + */ -- cgit v1.2.3 From a0ed2b0ef3f9259f245294c59e6f4695f29caddd Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Wed, 21 Dec 2016 14:33:32 +0100 Subject: Doc: added specs to Extending QML - Methods Example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I7386c2bd738776455a71bde8cffdcedb9e292b24 Reviewed-by: Venugopal Shivashankar Reviewed-by: Mitch Curtis Reviewed-by: Topi Reiniö --- examples/qml/doc/src/qml-extending.qdoc | 9 +++++++++ examples/qml/referenceexamples/methods/example.qml | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/examples/qml/doc/src/qml-extending.qdoc b/examples/qml/doc/src/qml-extending.qdoc index 0cb004be7d..b4174426a8 100644 --- a/examples/qml/doc/src/qml-extending.qdoc +++ b/examples/qml/doc/src/qml-extending.qdoc @@ -310,6 +310,15 @@ This example builds on: \li \l {Extending QML - Adding Types Example} \endlist +The Methods Example has an additional method in the \c BirthdayParty class: \c invite(). +\c invite() is declared with \l Q_INVOKABLE so that it can be +called from QML. + +\snippet referenceexamples/methods/birthdayparty.h 0 + +In \c example.qml, the \c invite() method is called in the \l [QML]{QtQml::Component::completed()}{Component.onCompleted} signal handler: + +\snippet referenceexamples/methods/example.qml 0 */ /*! diff --git a/examples/qml/referenceexamples/methods/example.qml b/examples/qml/referenceexamples/methods/example.qml index 58985c5d5f..197e6007e1 100644 --- a/examples/qml/referenceexamples/methods/example.qml +++ b/examples/qml/referenceexamples/methods/example.qml @@ -38,6 +38,7 @@ ** ****************************************************************************/ +// ![0] import QtQuick 2.0 import People 1.0 @@ -52,7 +53,6 @@ BirthdayParty { Person { name: "Anne Brown" } ] -// ![0] Component.onCompleted: invite("William Green") -// ![0] } +// ![0] -- cgit v1.2.3 From 208e118924d648a472dafd18d11f3404e30ad8be Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 9 Jan 2017 15:21:47 +0100 Subject: Fix crash in Canvas The Image based code path will delete the texture in textureForNextFrame() so deleting it again here is wrong. The convention is supposed to be that if the textureForNextFrame returns 0, it also deleted the input texture. So not deleting is correct for both Image and FBO. Change-Id: I45a5ef94c13358f3637f51ae2d21224518ea6a25 Reviewed-by: Laszlo Agocs --- src/quick/items/context2d/qquickcanvasitem.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index 212148b754..28e9173bf7 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -766,7 +766,6 @@ QSGNode *QQuickCanvasItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData if (!texture) { delete node; d->node = 0; - delete d->nodeTexture; d->nodeTexture = 0; if (d->textureProvider) { d->textureProvider->tex = 0; -- cgit v1.2.3 From 26051fd5724e56e0715bc56fde8e8464ff386bbc Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Tue, 10 Jan 2017 11:14:45 +0100 Subject: Blacklist tst_QQuickGraphicsInfo::testProperties() on linux Task-number: QTBUG-58039 Change-Id: Ib7a371c6dec7748b9c5257b6cf4dfb61efc7aa88 Reviewed-by: Simon Hausmann Reviewed-by: Lars Knoll --- tests/auto/quick/qquickgraphicsinfo/BLACKLIST | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/auto/quick/qquickgraphicsinfo/BLACKLIST diff --git a/tests/auto/quick/qquickgraphicsinfo/BLACKLIST b/tests/auto/quick/qquickgraphicsinfo/BLACKLIST new file mode 100644 index 0000000000..4cefc165f0 --- /dev/null +++ b/tests/auto/quick/qquickgraphicsinfo/BLACKLIST @@ -0,0 +1,3 @@ +[tst_QQuickGraphicsInfo::testProperties] +opensuse-42.1 +ubuntu-14.04 -- cgit v1.2.3 From 046d1a092b7b1ce7cb615d5e5e080a1cf8e41e10 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 1 Dec 2016 16:35:05 +0100 Subject: graph example: Fix MSVC warning about truncation of 'double' graph.cpp(105): warning C4305: 'argument': truncation from 'double' to 'float' Change-Id: I644dec9be8aeb1837a2b7402f7ab7c3b3beb7e1b Reviewed-by: Jesus Fernandez Reviewed-by: Shawn Rutledge --- examples/quick/scenegraph/graph/graph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/quick/scenegraph/graph/graph.cpp b/examples/quick/scenegraph/graph/graph.cpp index 389bd384c2..6048a1032c 100644 --- a/examples/quick/scenegraph/graph/graph.cpp +++ b/examples/quick/scenegraph/graph/graph.cpp @@ -102,7 +102,7 @@ QSGNode *Graph::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) n->background = new NoisyNode(window()); n->grid = new GridNode(); n->line = new LineNode(10, 0.5, QColor("steelblue")); - n->shadow = new LineNode(20, 0.2, QColor::fromRgbF(0.2, 0.2, 0.2, 0.4)); + n->shadow = new LineNode(20, 0.2f, QColor::fromRgbF(0.2, 0.2, 0.2, 0.4)); n->appendChildNode(n->background); n->appendChildNode(n->grid); -- cgit v1.2.3 From ba244f5400bfff1601cc6b373383b55956fcf6bb Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 28 Oct 2016 17:23:13 +0200 Subject: tst_qqmllocale: use QVERIFY() rather than QCOMPARE(, true) Use booleans as booleans, it's what they're for. Change-Id: I68c0ba5efcfd3556eeef043b179769e91c77cf03 Reviewed-by: Simon Hausmann --- tests/auto/qml/qqmllocale/tst_qqmllocale.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp index 4d2cae1523..44d11cdda3 100644 --- a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp +++ b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp @@ -1291,7 +1291,7 @@ void tst_qqmllocale::timeZoneUpdated() QQmlComponent c(&e, testFileUrl("timeZoneUpdated.qml")); QScopedPointer obj(c.create()); QVERIFY(obj); - QCOMPARE(obj->property("success").toBool(), true); + QVERIFY(obj->property("success").toBool()); // Change to Indian time setTimeZone(QByteArray("IST-05:30")); @@ -1302,7 +1302,7 @@ void tst_qqmllocale::timeZoneUpdated() setTimeZone(original); QMetaObject::invokeMethod(obj.data(), "resetTimeZone"); - QCOMPARE(obj->property("success").toBool(), true); + QVERIFY(obj->property("success").toBool()); } #endif -- cgit v1.2.3 From e7bfab82b45df088d15cbb4c5213ca94e260220d Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 9 Nov 2016 18:27:04 +0100 Subject: tst_qqmllocale: use unsetenv to clear environment variable tst_qqmllocale::timeZoneUpdated() was recording the prior time zone, frobbing it for the duration of its test, then restoring it. However, if TZ was previously unset, it got set to empty instead of being unset. This did not quite have the same effect; UTC ends up being used instead of the system default, with potential for conflict between system functions (that have attended to tzset) and third-party libraries (e.g. ICU) with internal state saved from before the change. Change-Id: I9f2147cd8858316e9ba5fd84d95dfc2c4538b0ab Reviewed-by: Matthew Vogt Reviewed-by: Simon Hausmann --- tests/auto/qml/qqmllocale/tst_qqmllocale.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp index 44d11cdda3..7a6cb7c929 100644 --- a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp +++ b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp @@ -1267,7 +1267,10 @@ QString DateFormatter::getLocalizedForm(const QString &isoTimestamp) // which will require linking to a different library to access that API. static void setTimeZone(const QByteArray &tz) { - qputenv("TZ", tz); + if (tz.isEmpty()) + qunsetenv("TZ"); + else + qputenv("TZ", tz); ::tzset(); // following left for future reference, see comment above -- cgit v1.2.3 From fb15a8c24209cee59f2d7c5f0d00f327a68014d6 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 4 Nov 2016 14:55:07 +0100 Subject: tst_qqmllocale: shuffle commentary on JS Date's month numbering While it departs from common date numbering, as used by QDateTime, the 0=Jan numbering used by JS's Date was copied from Java's Date, which (probably) copied it from ANSI C's struct tm; and C likes to count from zero. So don't call it weird; and let's comment on it where it's actually relevant (in JS code with the offset, rather than against uses of QDate, which uses 1=Jan numbering) and only once. Change-Id: I926138e88583339bec8641e3b28a642794dc217d Reviewed-by: Simon Hausmann --- tests/auto/qml/qqmllocale/data/date.qml | 1 + tests/auto/qml/qqmllocale/tst_qqmllocale.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/auto/qml/qqmllocale/data/date.qml b/tests/auto/qml/qqmllocale/data/date.qml index 3f58497d22..d8cd043cdf 100644 --- a/tests/auto/qml/qqmllocale/data/date.qml +++ b/tests/auto/qml/qqmllocale/data/date.qml @@ -7,6 +7,7 @@ QtObject { locale = Qt.locale(l) } + // Month number 9 is October: JS Date()'s month range is 0 to 11. function toLocaleString(fmt) { var d = new Date(2011, 9, 7, 18, 53, 48, 345); if (fmt < 0) diff --git a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp index 7a6cb7c929..e0836468fb 100644 --- a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp +++ b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp @@ -641,7 +641,7 @@ void tst_qqmllocale::dateToLocaleString() QVERIFY(obj); QDateTime dt; - dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11 + dt.setDate(QDate(2011, 10, 7)); dt.setTime(QTime(18, 53, 48, 345)); QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection, @@ -702,7 +702,7 @@ void tst_qqmllocale::dateToLocaleStringFormatted() QVERIFY(obj); QDateTime dt; - dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11 + dt.setDate(QDate(2011, 10, 7)); dt.setTime(QTime(18, 53, 48, 345)); QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection, @@ -733,7 +733,7 @@ void tst_qqmllocale::dateToLocaleDateString() QVERIFY(obj); QDateTime dt; - dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11 + dt.setDate(QDate(2011, 10, 7)); dt.setTime(QTime(18, 53, 48, 345)); QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection, @@ -794,7 +794,7 @@ void tst_qqmllocale::dateToLocaleDateStringFormatted() QVERIFY(obj); QDateTime dt; - dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11 + dt.setDate(QDate(2011, 10, 7)); dt.setTime(QTime(18, 53, 48, 345)); QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection, @@ -825,7 +825,7 @@ void tst_qqmllocale::dateToLocaleTimeString() QVERIFY(obj); QDateTime dt; - dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11 + dt.setDate(QDate(2011, 10, 7)); dt.setTime(QTime(18, 53, 48, 345)); QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection, @@ -886,7 +886,7 @@ void tst_qqmllocale::dateToLocaleTimeStringFormatted() QVERIFY(obj); QDateTime dt; - dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11 + dt.setDate(QDate(2011, 10, 7)); dt.setTime(QTime(18, 53, 48, 345)); QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection, -- cgit v1.2.3 From 676340aef688e6271bb3df456a45cf26be52f588 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 4 Nov 2016 16:04:36 +0100 Subject: tst_qqmllocale: simplify creation of a QDateTime Nine tests all used setDate and setTime on a default QDateTime, where just initializing it right, in one line, is simple, terse and easy to understand. This also allows it to be const. Change-Id: I77fd8b36b705cafc49f9020ae9280dfdcfece0d8 Reviewed-by: Simon Hausmann --- tests/auto/qml/qqmllocale/tst_qqmllocale.cpp | 36 +++++++--------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp index e0836468fb..1b83738ecf 100644 --- a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp +++ b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp @@ -640,9 +640,7 @@ void tst_qqmllocale::dateToLocaleString() QObject *obj = c.create(); QVERIFY(obj); - QDateTime dt; - dt.setDate(QDate(2011, 10, 7)); - dt.setTime(QTime(18, 53, 48, 345)); + const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection, Q_ARG(QVariant, QVariant(locale))); @@ -701,9 +699,7 @@ void tst_qqmllocale::dateToLocaleStringFormatted() QObject *obj = c.create(); QVERIFY(obj); - QDateTime dt; - dt.setDate(QDate(2011, 10, 7)); - dt.setTime(QTime(18, 53, 48, 345)); + const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection, Q_ARG(QVariant, QVariant(locale))); @@ -732,9 +728,7 @@ void tst_qqmllocale::dateToLocaleDateString() QObject *obj = c.create(); QVERIFY(obj); - QDateTime dt; - dt.setDate(QDate(2011, 10, 7)); - dt.setTime(QTime(18, 53, 48, 345)); + const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection, Q_ARG(QVariant, QVariant(locale))); @@ -793,9 +787,7 @@ void tst_qqmllocale::dateToLocaleDateStringFormatted() QObject *obj = c.create(); QVERIFY(obj); - QDateTime dt; - dt.setDate(QDate(2011, 10, 7)); - dt.setTime(QTime(18, 53, 48, 345)); + const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection, Q_ARG(QVariant, QVariant(locale))); @@ -824,9 +816,7 @@ void tst_qqmllocale::dateToLocaleTimeString() QObject *obj = c.create(); QVERIFY(obj); - QDateTime dt; - dt.setDate(QDate(2011, 10, 7)); - dt.setTime(QTime(18, 53, 48, 345)); + const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection, Q_ARG(QVariant, QVariant(locale))); @@ -885,9 +875,7 @@ void tst_qqmllocale::dateToLocaleTimeStringFormatted() QObject *obj = c.create(); QVERIFY(obj); - QDateTime dt; - dt.setDate(QDate(2011, 10, 7)); - dt.setTime(QTime(18, 53, 48, 345)); + const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection, Q_ARG(QVariant, QVariant(locale))); @@ -927,9 +915,7 @@ void tst_qqmllocale::dateFromLocaleString() QObject *obj = c.create(); QVERIFY(obj); - QDateTime dt; - dt.setDate(QDate(2011, 10, 7)); - dt.setTime(QTime(18, 53, 48, 345)); + const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection, Q_ARG(QVariant, QVariant(locale))); @@ -971,9 +957,7 @@ void tst_qqmllocale::dateFromLocaleDateString() QObject *obj = c.create(); QVERIFY(obj); - QDateTime dt; - dt.setDate(QDate(2011, 10, 7)); - dt.setTime(QTime(18, 53, 48, 345)); + const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection, Q_ARG(QVariant, QVariant(locale))); @@ -1015,9 +999,7 @@ void tst_qqmllocale::dateFromLocaleTimeString() QObject *obj = c.create(); QVERIFY(obj); - QDateTime dt; - dt.setDate(QDate(2011, 10, 7)); - dt.setTime(QTime(18, 53, 48, 345)); + const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection, Q_ARG(QVariant, QVariant(locale))); -- cgit v1.2.3 From 7277fdd603c940fb99c3eda183f5d75f32c57e7b Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 4 Nov 2016 16:20:06 +0100 Subject: tst_qqmllocale: avoid duplicating a QLocale::toString() call Reuse the same const QString in both places, in each of the functions that repeated this pattern. Change-Id: Ic20281692d84b3ad5257af9837957e0893452b1a Reviewed-by: Simon Hausmann --- tests/auto/qml/qqmllocale/tst_qqmllocale.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp index 1b83738ecf..d0ce83b997 100644 --- a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp +++ b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp @@ -921,13 +921,14 @@ void tst_qqmllocale::dateFromLocaleString() Q_ARG(QVariant, QVariant(locale))); QLocale l(locale); + const QString localeText(l.toString(dt, format)); QVariant val; QMetaObject::invokeMethod(obj, "fromLocaleString", Qt::DirectConnection, Q_RETURN_ARG(QVariant, val), - Q_ARG(QVariant, QVariant(l.toString(dt, format))), + Q_ARG(QVariant, QVariant(localeText)), Q_ARG(QVariant, QVariant(format))); - QDateTime pd = l.toDateTime(l.toString(dt, format), format); + QDateTime pd = l.toDateTime(localeText, format); QCOMPARE(val.toDateTime(), pd); } @@ -963,13 +964,14 @@ void tst_qqmllocale::dateFromLocaleDateString() Q_ARG(QVariant, QVariant(locale))); QLocale l(locale); + const QString localeText(l.toString(dt, format)); QVariant val; QMetaObject::invokeMethod(obj, "fromLocaleDateString", Qt::DirectConnection, Q_RETURN_ARG(QVariant, val), - Q_ARG(QVariant, QVariant(l.toString(dt, format))), + Q_ARG(QVariant, QVariant(localeText)), Q_ARG(QVariant, QVariant(format))); - QDate pd = l.toDate(l.toString(dt, format), format); + QDate pd = l.toDate(localeText, format); QCOMPARE(val.toDate(), pd); } @@ -1005,13 +1007,14 @@ void tst_qqmllocale::dateFromLocaleTimeString() Q_ARG(QVariant, QVariant(locale))); QLocale l(locale); + const QString localeText(l.toString(dt, format)); QVariant val; QMetaObject::invokeMethod(obj, "fromLocaleTimeString", Qt::DirectConnection, Q_RETURN_ARG(QVariant, val), - Q_ARG(QVariant, QVariant(l.toString(dt, format))), + Q_ARG(QVariant, QVariant(localeText)), Q_ARG(QVariant, QVariant(format))); - QTime pd = l.toTime(l.toString(dt, format), format); + QTime pd = l.toTime(localeText, format); QCOMPARE(val.toTime(), pd); } -- cgit v1.2.3 From 07a55e28a8b1f26933d171f3e81d6ee13d0a74f4 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 5 Jan 2017 16:55:48 +0100 Subject: Remove Q_FLAGS about a enum/flags that don't exist at all Change-Id: Ie6954aef0e28cd1356a195d34b92b8df9d6fb9c7 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/qml/qml/qqmlabstracturlinterceptor.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qml/qml/qqmlabstracturlinterceptor.h b/src/qml/qml/qqmlabstracturlinterceptor.h index dfb8a46027..665b37fb3a 100644 --- a/src/qml/qml/qqmlabstracturlinterceptor.h +++ b/src/qml/qml/qqmlabstracturlinterceptor.h @@ -47,7 +47,6 @@ QT_BEGIN_NAMESPACE class Q_QML_EXPORT QQmlAbstractUrlInterceptor { - Q_FLAGS(InterceptionPoint) public: enum DataType { //Matches QQmlDataBlob::Type QmlFile = 0, -- cgit v1.2.3 From 6746db54f2adb40b836ce41101462bc38604749f Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 11 Jan 2017 11:44:58 +0100 Subject: QML tooling: Make sure we signal object creation also from QQmlIncubator We have to call the QQmlEngineDebugService back from QQmlObjectCreator rather than QQmlComponent, as there are more ways to create an object. We also add the new instance to the global instance list if only the V4 debug service is active, as both QQmlEngineDebugService and QV4DebugService use it. Change-Id: I5dcc71b2e91049bc19ec70d7b87959a61c9b6b75 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlcomponent.cpp | 11 --------- src/qml/qml/qqmlobjectcreator.cpp | 13 ++++++++++ .../tst_qqmlenginedebugservice.cpp | 28 ++++++++++++++++++++++ .../qml/debugger/shared/qqmlenginedebugclient.cpp | 4 +++- .../qml/debugger/shared/qqmlenginedebugclient.h | 2 +- 5 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 8be5172cd4..15e09f0b85 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -47,8 +47,6 @@ #include "qqml.h" #include "qqmlengine.h" #include "qqmlbinding_p.h" -#include -#include #include "qqmlincubator.h" #include "qqmlincubator_p.h" #include @@ -876,15 +874,6 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context) depthIncreased = false; } - if (rv) { - if (QQmlEngineDebugService *service = - QQmlDebugConnector::service()) { - if (!context->isInternal) - context->asQQmlContextPrivate()->instances.append(rv); - service->objectCreated(engine, rv); - } - } - return rv; } diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 2e2a3fb303..09936f6e7a 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -53,6 +53,8 @@ #include #include #include +#include +#include QT_USE_NAMESPACE @@ -216,6 +218,17 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI phase = ObjectsCreated; + if (instance) { + if (QQmlEngineDebugService *service + = QQmlDebugConnector::service()) { + if (!parentContext->isInternal) + parentContext->asQQmlContextPrivate()->instances.append(instance); + service->objectCreated(engine, instance); + } else if (!parentContext->isInternal && QQmlDebugConnector::service()) { + parentContext->asQQmlContextPrivate()->instances.append(instance); + } + } + return instance; } diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp index 40e19d375d..8c30a82317 100644 --- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp +++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -136,6 +137,7 @@ private slots: void regression_QTCREATORBUG_7451(); void queryObjectWithNonStreamableTypes(); + void asynchronousCreate(); }; QmlDebugObjectReference tst_QQmlEngineDebugService::findRootObject( @@ -1220,6 +1222,32 @@ void tst_QQmlEngineDebugService::queryObjectTree() QCOMPARE(findProperty(animation.properties,"duration").value.toInt(), 100); } +void tst_QQmlEngineDebugService::asynchronousCreate() { + QmlDebugObjectReference object; + auto connection = connect(m_dbg, &QQmlEngineDebugClient::newObject, this, [&](int objectId) { + object.debugId = objectId; + }); + + QByteArray asynchronousComponent = "import QtQuick 2.5\n" + "Rectangle { id: asyncRect }"; + QQmlComponent component(m_engine); + component.setData(asynchronousComponent, QUrl::fromLocalFile("")); + QVERIFY(component.isReady()); // fails if bad syntax + QQmlIncubator incubator(QQmlIncubator::Asynchronous); + component.create(incubator); + + QVERIFY(m_dbg->object().idString != QLatin1String("asyncRect")); + + QTRY_VERIFY(object.debugId != -1); + disconnect(connection); + + bool success = false; + m_dbg->queryObject(object, &success); + QVERIFY(success); + + QTRY_COMPARE(m_dbg->object().idString, QLatin1String("asyncRect")); +} + int main(int argc, char *argv[]) { int _argc = argc + 1; diff --git a/tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp b/tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp index 3ad7beb7ff..3e27951d78 100644 --- a/tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp +++ b/tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp @@ -489,7 +489,9 @@ void QQmlEngineDebugClient::messageReceived(const QByteArray &data) return; } else if (type == "OBJECT_CREATED") { - emit newObjects(); + int engineId, objectId, parentId; + ds >> engineId >> objectId >> parentId; + emit newObject(objectId); return; } else if (type == "SET_BINDING_R") { ds >> m_valid; diff --git a/tests/auto/qml/debugger/shared/qqmlenginedebugclient.h b/tests/auto/qml/debugger/shared/qqmlenginedebugclient.h index a64a77e13e..5d74f2d43c 100644 --- a/tests/auto/qml/debugger/shared/qqmlenginedebugclient.h +++ b/tests/auto/qml/debugger/shared/qqmlenginedebugclient.h @@ -213,7 +213,7 @@ public: bool valid() { return m_valid; } signals: - void newObjects(); + void newObject(int objectId); void valueChanged(QByteArray,QVariant); void result(); -- cgit v1.2.3 From 3215ebbc33c5d5fce21dde39daefced34ab235ba Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 6 Jan 2017 14:06:31 +0100 Subject: Minor assembler cleanup Move code from the Assembler helper-class into the .cpp file that has the rest of the Assembler class implementation. Change-Id: I4e9fb264216a078a3ee11119d7610fd108ddf8c7 Reviewed-by: Lars Knoll --- src/qml/jit/qv4assembler.cpp | 172 +++++++++++++++++++++++++++++++++++++++++++ src/qml/jit/qv4isel_masm.cpp | 169 ------------------------------------------ 2 files changed, 172 insertions(+), 169 deletions(-) diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp index e1acc33f82..51cba7fb0c 100644 --- a/src/qml/jit/qv4assembler.cpp +++ b/src/qml/jit/qv4assembler.cpp @@ -52,6 +52,8 @@ #include #include +#include +#include #if ENABLE(ASSEMBLER) @@ -496,4 +498,174 @@ void Assembler::setStackLayout(int maxArgCountForBuiltins, int regularRegistersT _stackLayout.reset(new StackLayout(_function, maxArgCountForBuiltins, regularRegistersToSave, fpRegistersToSave)); } + +namespace { +class QIODevicePrintStream: public FilePrintStream +{ + Q_DISABLE_COPY(QIODevicePrintStream) + +public: + explicit QIODevicePrintStream(QIODevice *dest) + : FilePrintStream(0) + , dest(dest) + , buf(4096, '0') + { + Q_ASSERT(dest); + } + + ~QIODevicePrintStream() + {} + + void vprintf(const char* format, va_list argList) WTF_ATTRIBUTE_PRINTF(2, 0) + { + const int written = qvsnprintf(buf.data(), buf.size(), format, argList); + if (written > 0) + dest->write(buf.constData(), written); + memset(buf.data(), 0, qMin(written, buf.size())); + } + + void flush() + {} + +private: + QIODevice *dest; + QByteArray buf; +}; +} // anonymous namespace + +static void printDisassembledOutputWithCalls(QByteArray processedOutput, const QHash& functions) +{ + for (QHash::ConstIterator it = functions.begin(), end = functions.end(); + it != end; ++it) { + const QByteArray ptrString = "0x" + QByteArray::number(quintptr(it.key()), 16); + int idx = processedOutput.indexOf(ptrString); + if (idx < 0) + continue; + idx = processedOutput.lastIndexOf('\n', idx); + if (idx < 0) + continue; + processedOutput = processedOutput.insert(idx, QByteArrayLiteral(" ; call ") + it.value()); + } + + qDebug("%s", processedOutput.constData()); +} + +#if defined(Q_OS_LINUX) +static FILE *pmap; + +static void qt_closePmap() +{ + if (pmap) { + fclose(pmap); + pmap = 0; + } +} + +#endif + +JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize) +{ + Label endOfCode = label(); + + { + for (size_t i = 0, ei = _patches.size(); i != ei; ++i) { + Label target = _addrs.at(i); + Q_ASSERT(target.isSet()); + for (Jump jump : qAsConst(_patches.at(i))) + jump.linkTo(target, this); + } + } + + JSC::JSGlobalData dummy(_executableAllocator); + JSC::LinkBuffer linkBuffer(dummy, this, 0); + + for (const DataLabelPatch &p : qAsConst(_dataLabelPatches)) + linkBuffer.patch(p.dataLabel, linkBuffer.locationOf(p.target)); + + // link exception handlers + for (Jump jump : qAsConst(exceptionPropagationJumps)) + linkBuffer.link(jump, linkBuffer.locationOf(exceptionReturnLabel)); + + { + for (size_t i = 0, ei = _labelPatches.size(); i != ei; ++i) { + Label target = _addrs.at(i); + Q_ASSERT(target.isSet()); + for (DataLabelPtr label : _labelPatches.at(i)) + linkBuffer.patch(label, linkBuffer.locationOf(target)); + } + } + + *codeSize = linkBuffer.offsetOf(endOfCode); + + QByteArray name; + + JSC::MacroAssemblerCodeRef codeRef; + + static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_ASM"); + if (showCode) { + QHash functions; +#ifndef QT_NO_DEBUG + for (CallInfo call : qAsConst(_callInfos)) + functions[linkBuffer.locationOf(call.label).dataLocation()] = call.functionName; +#endif + + QBuffer buf; + buf.open(QIODevice::WriteOnly); + WTF::setDataFile(new QIODevicePrintStream(&buf)); + + name = _function->name->toUtf8(); + if (name.isEmpty()) + name = "IR::Function(0x" + QByteArray::number(quintptr(_function), 16) + ')'; + codeRef = linkBuffer.finalizeCodeWithDisassembly("%s", name.data()); + + WTF::setDataFile(stderr); + printDisassembledOutputWithCalls(buf.data(), functions); + } else { + codeRef = linkBuffer.finalizeCodeWithoutDisassembly(); + } + +#if defined(Q_OS_LINUX) + // This implements writing of JIT'd addresses so that perf can find the + // symbol names. + // + // Perf expects the mapping to be in a certain place and have certain + // content, for more information, see: + // https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/jit-interface.txt + static bool doProfile = !qEnvironmentVariableIsEmpty("QV4_PROFILE_WRITE_PERF_MAP"); + static bool profileInitialized = false; + if (doProfile && !profileInitialized) { + profileInitialized = true; + + char pname[PATH_MAX]; + snprintf(pname, PATH_MAX - 1, "/tmp/perf-%lu.map", + (unsigned long)QCoreApplication::applicationPid()); + + pmap = fopen(pname, "w"); + if (!pmap) + qWarning("QV4: Can't write %s, call stacks will not contain JavaScript function names", pname); + + // make sure we clean up nicely + std::atexit(qt_closePmap); + } + + if (pmap) { + // this may have been pre-populated, if QV4_SHOW_ASM was on + if (name.isEmpty()) { + name = _function->name->toUtf8(); + if (name.isEmpty()) + name = "IR::Function(0x" + QByteArray::number(quintptr(_function), 16) + ')'; + } + + fprintf(pmap, "%llx %x %.*s\n", + (long long unsigned int)codeRef.code().executableAddress(), + *codeSize, + name.length(), + name.constData()); + fflush(pmap); + } +#endif + + return codeRef; +} + #endif diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index c5d612ae65..ed32965efa 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -68,175 +68,6 @@ using namespace QV4; using namespace QV4::JIT; -namespace { -class QIODevicePrintStream: public FilePrintStream -{ - Q_DISABLE_COPY(QIODevicePrintStream) - -public: - explicit QIODevicePrintStream(QIODevice *dest) - : FilePrintStream(0) - , dest(dest) - , buf(4096, '0') - { - Q_ASSERT(dest); - } - - ~QIODevicePrintStream() - {} - - void vprintf(const char* format, va_list argList) WTF_ATTRIBUTE_PRINTF(2, 0) - { - const int written = qvsnprintf(buf.data(), buf.size(), format, argList); - if (written > 0) - dest->write(buf.constData(), written); - memset(buf.data(), 0, qMin(written, buf.size())); - } - - void flush() - {} - -private: - QIODevice *dest; - QByteArray buf; -}; -} // anonymous namespace - -static void printDisassembledOutputWithCalls(QByteArray processedOutput, const QHash& functions) -{ - for (QHash::ConstIterator it = functions.begin(), end = functions.end(); - it != end; ++it) { - const QByteArray ptrString = "0x" + QByteArray::number(quintptr(it.key()), 16); - int idx = processedOutput.indexOf(ptrString); - if (idx < 0) - continue; - idx = processedOutput.lastIndexOf('\n', idx); - if (idx < 0) - continue; - processedOutput = processedOutput.insert(idx, QByteArrayLiteral(" ; call ") + it.value()); - } - - qDebug("%s", processedOutput.constData()); -} - -#if defined(Q_OS_LINUX) -static FILE *pmap; - -static void qt_closePmap() -{ - if (pmap) { - fclose(pmap); - pmap = 0; - } -} - -#endif - -JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize) -{ - Label endOfCode = label(); - - { - for (size_t i = 0, ei = _patches.size(); i != ei; ++i) { - Label target = _addrs.at(i); - Q_ASSERT(target.isSet()); - for (Jump jump : qAsConst(_patches.at(i))) - jump.linkTo(target, this); - } - } - - JSC::JSGlobalData dummy(_executableAllocator); - JSC::LinkBuffer linkBuffer(dummy, this, 0); - - for (const DataLabelPatch &p : qAsConst(_dataLabelPatches)) - linkBuffer.patch(p.dataLabel, linkBuffer.locationOf(p.target)); - - // link exception handlers - for (Jump jump : qAsConst(exceptionPropagationJumps)) - linkBuffer.link(jump, linkBuffer.locationOf(exceptionReturnLabel)); - - { - for (size_t i = 0, ei = _labelPatches.size(); i != ei; ++i) { - Label target = _addrs.at(i); - Q_ASSERT(target.isSet()); - for (DataLabelPtr label : _labelPatches.at(i)) - linkBuffer.patch(label, linkBuffer.locationOf(target)); - } - } - - *codeSize = linkBuffer.offsetOf(endOfCode); - - QByteArray name; - - JSC::MacroAssemblerCodeRef codeRef; - - static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_ASM"); - if (showCode) { - QHash functions; -#ifndef QT_NO_DEBUG - for (CallInfo call : qAsConst(_callInfos)) - functions[linkBuffer.locationOf(call.label).dataLocation()] = call.functionName; -#endif - - QBuffer buf; - buf.open(QIODevice::WriteOnly); - WTF::setDataFile(new QIODevicePrintStream(&buf)); - - name = _function->name->toUtf8(); - if (name.isEmpty()) - name = "IR::Function(0x" + QByteArray::number(quintptr(_function), 16) + ')'; - codeRef = linkBuffer.finalizeCodeWithDisassembly("%s", name.data()); - - WTF::setDataFile(stderr); - printDisassembledOutputWithCalls(buf.data(), functions); - } else { - codeRef = linkBuffer.finalizeCodeWithoutDisassembly(); - } - -#if defined(Q_OS_LINUX) - // This implements writing of JIT'd addresses so that perf can find the - // symbol names. - // - // Perf expects the mapping to be in a certain place and have certain - // content, for more information, see: - // https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/jit-interface.txt - static bool doProfile = !qEnvironmentVariableIsEmpty("QV4_PROFILE_WRITE_PERF_MAP"); - static bool profileInitialized = false; - if (doProfile && !profileInitialized) { - profileInitialized = true; - - char pname[PATH_MAX]; - snprintf(pname, PATH_MAX - 1, "/tmp/perf-%lu.map", - (unsigned long)QCoreApplication::applicationPid()); - - pmap = fopen(pname, "w"); - if (!pmap) - qWarning("QV4: Can't write %s, call stacks will not contain JavaScript function names", pname); - - // make sure we clean up nicely - std::atexit(qt_closePmap); - } - - if (pmap) { - // this may have been pre-populated, if QV4_SHOW_ASM was on - if (name.isEmpty()) { - name = _function->name->toUtf8(); - if (name.isEmpty()) - name = "IR::Function(0x" + QByteArray::number(quintptr(_function), 16) + ')'; - } - - fprintf(pmap, "%llx %x %.*s\n", - (long long unsigned int)codeRef.code().executableAddress(), - *codeSize, - name.length(), - name.constData()); - fflush(pmap); - } -#endif - - return codeRef; -} - InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory) : EvalInstructionSelection(execAllocator, module, jsGenerator, iselFactory) , _block(0) -- cgit v1.2.3 From 6cab0ee6e2afe31b451ef99df67c7fc8f3317909 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 10 Jan 2017 14:22:37 +0100 Subject: Break circular assembler dependency The QV4::Assembler does not need a reference to the ISel that uses the assembler, a reference to the JS unit generator for string registration is sufficient. Change-Id: I9e929e4d0aecbf0144296f85cb8d208296f28003 Reviewed-by: Lars Knoll --- src/qml/jit/qv4assembler.cpp | 10 +++++----- src/qml/jit/qv4assembler_p.h | 4 ++-- src/qml/jit/qv4isel_masm.cpp | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp index 51cba7fb0c..018396318e 100644 --- a/src/qml/jit/qv4assembler.cpp +++ b/src/qml/jit/qv4assembler.cpp @@ -148,11 +148,11 @@ bool CompilationUnit::memoryMapCode(QString *errorString) const Assembler::VoidType Assembler::Void; -Assembler::Assembler(InstructionSelection *isel, IR::Function* function, QV4::ExecutableAllocator *executableAllocator) +Assembler::Assembler(QV4::Compiler::JSUnitGenerator *jsGenerator, IR::Function* function, QV4::ExecutableAllocator *executableAllocator) : _function(function) , _nextBlock(0) , _executableAllocator(executableAllocator) - , _isel(isel) + , _jsGenerator(jsGenerator) { _addrs.resize(_function->basicBlockCount()); _patches.resize(_function->basicBlockCount()); @@ -303,7 +303,7 @@ Assembler::Pointer Assembler::loadStringAddress(RegisterID reg, const QString &s loadPtr(Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), Assembler::ScratchRegister); loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(QV4::Heap::ExecutionContext, compilationUnit)), Assembler::ScratchRegister); loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(QV4::CompiledData::CompilationUnit, runtimeStrings)), reg); - const int id = _isel->registerString(string); + const int id = _jsGenerator->registerString(string); return Pointer(reg, id * sizeof(QV4::String*)); } @@ -316,13 +316,13 @@ Assembler::Address Assembler::loadConstant(const Primitive &v, RegisterID baseRe { loadPtr(Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), baseReg); loadPtr(Address(baseReg, qOffsetOf(QV4::Heap::ExecutionContext, constantTable)), baseReg); - const int index = _isel->jsUnitGenerator()->registerConstant(v.asReturnedValue()); + const int index = _jsGenerator->registerConstant(v.asReturnedValue()); return Address(baseReg, index * sizeof(QV4::Value)); } void Assembler::loadStringRef(RegisterID reg, const QString &string) { - const int id = _isel->registerString(string); + const int id = _jsGenerator->registerString(string); move(TrustedImm32(id), reg); } diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h index 94478cd9cd..de9c246ed6 100644 --- a/src/qml/jit/qv4assembler_p.h +++ b/src/qml/jit/qv4assembler_p.h @@ -111,7 +111,7 @@ class Assembler : public JSC::MacroAssembler, public TargetPlatform Q_DISABLE_COPY(Assembler) public: - Assembler(InstructionSelection *isel, IR::Function* function, QV4::ExecutableAllocator *executableAllocator); + Assembler(QV4::Compiler::JSUnitGenerator *jsGenerator, IR::Function* function, QV4::ExecutableAllocator *executableAllocator); // Explicit type to allow distinguishing between // pushing an address itself or the value it points @@ -1092,7 +1092,7 @@ private: IR::BasicBlock *_nextBlock; QV4::ExecutableAllocator *_executableAllocator; - InstructionSelection *_isel; + QV4::Compiler::JSUnitGenerator *_jsGenerator; }; template diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index ed32965efa..20752b5c34 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -109,7 +109,7 @@ void InstructionSelection::run(int functionIndex) qSwap(_removableJumps, removableJumps); Assembler* oldAssembler = _as; - _as = new Assembler(this, _function, executableAllocator); + _as = new Assembler(jsGenerator, _function, executableAllocator); _as->setStackLayout(6, // 6 == max argc for calls to built-ins with an argument array regularRegistersToSave.size(), fpRegistersToSave.size()); -- cgit v1.2.3 From 971314dbb56c3761bb38abda8e257fd5f8502d00 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 6 Jan 2017 16:36:57 +0100 Subject: Binop assembler cleanup In preparation for the binop generator to work with different assemblers, we can bring some of the externally prefixed Assembler:: types into the Binop class namespace. That makes the code easier to read (less visual noise) and centralizes the dependency to the external type to one place (the using statements). Change-Id: Ib7700689196f8e54bba1f3ab6de3bf85ed93ff87 Reviewed-by: Lars Knoll Reviewed-by: Qt CI Bot --- src/qml/jit/qv4binop.cpp | 86 +++++++++++++++++++++--------------------- src/qml/jit/qv4binop_p.h | 98 ++++++++++++++++++++++++++---------------------- 2 files changed, 97 insertions(+), 87 deletions(-) diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp index 9c535bb0bb..d2758c4a47 100644 --- a/src/qml/jit/qv4binop.cpp +++ b/src/qml/jit/qv4binop.cpp @@ -112,7 +112,7 @@ void Binop::generate(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target) return; } - Assembler::Jump done; + Jump done; if (lhs->type != IR::StringType && rhs->type != IR::StringType) done = genInlineBinop(lhs, rhs, target); @@ -129,13 +129,13 @@ void Binop::generate(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target) RuntimeCall context(info.contextImplementation); if (fallBack.isValid()) { as->generateFunctionCallImp(info.needsExceptionCheck, target, info.name, fallBack, - Assembler::PointerToValue(lhs), - Assembler::PointerToValue(rhs)); + PointerToValue(lhs), + PointerToValue(rhs)); } else if (context.isValid()) { as->generateFunctionCallImp(info.needsExceptionCheck, target, info.name, context, Assembler::EngineRegister, - Assembler::PointerToValue(lhs), - Assembler::PointerToValue(rhs)); + PointerToValue(lhs), + PointerToValue(rhs)); } else { Q_ASSERT(!"unreachable"); } @@ -148,9 +148,9 @@ void Binop::generate(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target) void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target) { IR::Temp *targetTemp = target->asTemp(); - Assembler::FPRegisterID targetReg; + FPRegisterID targetReg; if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) - targetReg = (Assembler::FPRegisterID) targetTemp->index; + targetReg = (FPRegisterID) targetTemp->index; else targetReg = Assembler::FPGpr0; @@ -162,7 +162,7 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target) #if CPU(X86) if (IR::Const *c = rhs->asConst()) { // Y = X + constant -> Y = X; Y += [constant-address] as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg); - Assembler::Address addr = as->loadConstant(c, Assembler::ScratchRegister); + Address addr = as->loadConstant(c, Assembler::ScratchRegister); as->addDouble(addr, targetReg); break; } @@ -184,7 +184,7 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target) #if CPU(X86) if (IR::Const *c = rhs->asConst()) { // Y = X * constant -> Y = X; Y *= [constant-address] as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg); - Assembler::Address addr = as->loadConstant(c, Assembler::ScratchRegister); + Address addr = as->loadConstant(c, Assembler::ScratchRegister); as->mulDouble(addr, targetReg); break; } @@ -203,7 +203,7 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target) #if CPU(X86) if (IR::Const *c = rhs->asConst()) { // Y = X - constant -> Y = X; Y -= [constant-address] as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg); - Assembler::Address addr = as->loadConstant(c, Assembler::ScratchRegister); + Address addr = as->loadConstant(c, Assembler::ScratchRegister); as->subDouble(addr, targetReg); break; } @@ -231,7 +231,7 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target) #if CPU(X86) if (IR::Const *c = rhs->asConst()) { // Y = X / constant -> Y = X; Y /= [constant-address] as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg); - Assembler::Address addr = as->loadConstant(c, Assembler::ScratchRegister); + Address addr = as->loadConstant(c, Assembler::ScratchRegister); as->divDouble(addr, targetReg); break; } @@ -258,9 +258,9 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target) default: { Q_ASSERT(target->type == IR::BoolType); - Assembler::Jump trueCase = as->branchDouble(false, op, lhs, rhs); + Jump trueCase = as->branchDouble(false, op, lhs, rhs); as->storeBool(false, target); - Assembler::Jump done = as->jump(); + Jump done = as->jump(); trueCase.link(as); as->storeBool(true, target); done.link(as); @@ -305,13 +305,13 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta bool inplaceOpWithAddress = false; IR::Temp *targetTemp = target->asTemp(); - Assembler::RegisterID targetReg = Assembler::ReturnValueRegister; + RegisterID targetReg = Assembler::ReturnValueRegister; if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) { IR::Temp *rhs = rightSource->asTemp(); if (!rhs || rhs->kind != IR::Temp::PhysicalRegister || rhs->index != targetTemp->index) { // We try to load leftSource into the target's register, but we can't do that if // the target register is the same as rightSource. - targetReg = (Assembler::RegisterID) targetTemp->index; + targetReg = (RegisterID) targetTemp->index; } else if (rhs && rhs->kind == IR::Temp::PhysicalRegister && targetTemp->index == rhs->index) { // However, if the target register is the same as the rightSource register, we can flip // the operands for certain operations. @@ -323,7 +323,7 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta case IR::OpMul: // X = Y op X -> X = X op Y (or rephrased: X op= Y (so an in-place operation)) std::swap(leftSource, rightSource); - targetReg = (Assembler::RegisterID) targetTemp->index; + targetReg = (RegisterID) targetTemp->index; break; case IR::OpLShift: @@ -368,7 +368,7 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta && targetTemp->kind == IR::Temp::PhysicalRegister && targetTemp->index == rightSource->asTemp()->index) { // X = Y - X -> Tmp = X; X = Y; X -= Tmp - targetReg = (Assembler::RegisterID) targetTemp->index; + targetReg = (RegisterID) targetTemp->index; as->move(targetReg, Assembler::ScratchRegister); as->move(as->toInt32Register(leftSource, targetReg), targetReg); as->sub32(Assembler::ScratchRegister, targetReg); @@ -384,7 +384,7 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta case IR::OpURShift: if (IR::Const *c = rightSource->asConst()) { if ((QV4::Primitive::toUInt32(c->value) & 0x1f) == 0) { - Assembler::RegisterID r = as->toInt32Register(leftSource, targetReg); + RegisterID r = as->toInt32Register(leftSource, targetReg); as->storeInt32(r, target); return true; } @@ -395,10 +395,10 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta break; } - Assembler::RegisterID l = as->toInt32Register(leftSource, targetReg); + RegisterID l = as->toInt32Register(leftSource, targetReg); if (IR::Const *c = rightSource->asConst()) { // All cases of Y = X op Const - Assembler::TrustedImm32 r(int(c->value)); - Assembler::TrustedImm32 ur(QV4::Primitive::toUInt32(c->value) & 0x1f); + TrustedImm32 r(int(c->value)); + TrustedImm32 ur(QV4::Primitive::toUInt32(c->value) & 0x1f); switch (op) { case IR::OpBitAnd: as->and32(r, l, targetReg); break; @@ -419,7 +419,7 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta return false; } } else if (inplaceOpWithAddress) { // All cases of X = X op [address-of-Y] - Assembler::Pointer rhsAddr = as->loadAddress(Assembler::ScratchRegister, rightSource); + Pointer rhsAddr = as->loadAddress(Assembler::ScratchRegister, rightSource); switch (op) { case IR::OpBitAnd: as->and32(rhsAddr, targetReg); break; case IR::OpBitOr: as->or32 (rhsAddr, targetReg); break; @@ -433,7 +433,7 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta return false; } } else { // All cases of Z = X op Y - Assembler::RegisterID r = as->toInt32Register(rightSource, Assembler::ScratchRegister); + RegisterID r = as->toInt32Register(rightSource, Assembler::ScratchRegister); switch (op) { case IR::OpBitAnd: as->and32(l, r, targetReg); break; case IR::OpBitOr: as->or32 (l, r, targetReg); break; @@ -452,10 +452,10 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta // Not all CPUs accept shifts over more than 31 bits, and some CPUs (like ARM) will do // surprising stuff when shifting over 0 bits. #define CHECK_RHS(op) { \ - as->and32(Assembler::TrustedImm32(0x1f), r, Assembler::ScratchRegister); \ - Assembler::Jump notZero = as->branch32(Assembler::NotEqual, Assembler::ScratchRegister, Assembler::TrustedImm32(0)); \ + as->and32(TrustedImm32(0x1f), r, Assembler::ScratchRegister); \ + Jump notZero = as->branch32(RelationalCondition::NotEqual, Assembler::ScratchRegister, TrustedImm32(0)); \ as->move(l, targetReg); \ - Assembler::Jump done = as->jump(); \ + Jump done = as->jump(); \ notZero.link(as); \ op; \ done.link(as); \ @@ -493,7 +493,7 @@ static inline Assembler::FPRegisterID getFreeFPReg(IR::Expr *shouldNotOverlap, u Assembler::Jump Binop::genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target) { - Assembler::Jump done; + Jump done; // Try preventing a call for a few common binary operations. This is used in two cases: // - no register allocation was performed (not available for the platform, or the IR was @@ -505,10 +505,10 @@ Assembler::Jump Binop::genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSourc // register. switch (op) { case IR::OpAdd: { - Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2); - Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4); - Assembler::Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg); - Assembler::Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg); + FPRegisterID lReg = getFreeFPReg(rightSource, 2); + FPRegisterID rReg = getFreeFPReg(leftSource, 4); + Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg); + Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg); as->addDouble(rReg, lReg); as->storeDouble(lReg, target); @@ -520,10 +520,10 @@ Assembler::Jump Binop::genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSourc rightIsNoDbl.link(as); } break; case IR::OpMul: { - Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2); - Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4); - Assembler::Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg); - Assembler::Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg); + FPRegisterID lReg = getFreeFPReg(rightSource, 2); + FPRegisterID rReg = getFreeFPReg(leftSource, 4); + Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg); + Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg); as->mulDouble(rReg, lReg); as->storeDouble(lReg, target); @@ -535,10 +535,10 @@ Assembler::Jump Binop::genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSourc rightIsNoDbl.link(as); } break; case IR::OpSub: { - Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2); - Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4); - Assembler::Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg); - Assembler::Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg); + FPRegisterID lReg = getFreeFPReg(rightSource, 2); + FPRegisterID rReg = getFreeFPReg(leftSource, 4); + Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg); + Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg); as->subDouble(rReg, lReg); as->storeDouble(lReg, target); @@ -550,10 +550,10 @@ Assembler::Jump Binop::genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSourc rightIsNoDbl.link(as); } break; case IR::OpDiv: { - Assembler::FPRegisterID lReg = getFreeFPReg(rightSource, 2); - Assembler::FPRegisterID rReg = getFreeFPReg(leftSource, 4); - Assembler::Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg); - Assembler::Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg); + FPRegisterID lReg = getFreeFPReg(rightSource, 2); + FPRegisterID rReg = getFreeFPReg(leftSource, 4); + Jump leftIsNoDbl = as->genTryDoubleConversion(leftSource, lReg); + Jump rightIsNoDbl = as->genTryDoubleConversion(rightSource, rReg); as->divDouble(rReg, lReg); as->storeDouble(lReg, target); diff --git a/src/qml/jit/qv4binop_p.h b/src/qml/jit/qv4binop_p.h index 37601f54ba..3742e99e5a 100644 --- a/src/qml/jit/qv4binop_p.h +++ b/src/qml/jit/qv4binop_p.h @@ -67,13 +67,23 @@ struct Binop { , op(operation) {} + using Jump = Assembler::Jump; + using Address = Assembler::Address; + using RegisterID = Assembler::RegisterID; + using FPRegisterID = Assembler::FPRegisterID; + using TrustedImm32 = Assembler::TrustedImm32; + using ResultCondition = Assembler::ResultCondition; + using RelationalCondition = Assembler::RelationalCondition; + using Pointer = Assembler::Pointer; + using PointerToValue = Assembler::PointerToValue; + void generate(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target); void doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target); bool int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target); - Assembler::Jump genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target); + Jump genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target); - typedef Assembler::Jump (Binop::*MemRegOp)(Assembler::Address, Assembler::RegisterID); - typedef Assembler::Jump (Binop::*ImmRegOp)(Assembler::TrustedImm32, Assembler::RegisterID); + typedef Jump (Binop::*MemRegOp)(Address, RegisterID); + typedef Jump (Binop::*ImmRegOp)(TrustedImm32, RegisterID); struct OpInfo { const char *name; @@ -88,97 +98,97 @@ struct Binop { static const OpInfo &operation(IR::AluOp operation) { return operations[operation]; } - Assembler::Jump inline_add32(Assembler::Address addr, Assembler::RegisterID reg) + Jump inline_add32(Address addr, RegisterID reg) { #if HAVE(ALU_OPS_WITH_MEM_OPERAND) - return as->branchAdd32(Assembler::Overflow, addr, reg); + return as->branchAdd32(ResultCondition::Overflow, addr, reg); #else as->load32(addr, Assembler::ScratchRegister); - return as->branchAdd32(Assembler::Overflow, Assembler::ScratchRegister, reg); + return as->branchAdd32(ResultCondition::Overflow, Assembler::ScratchRegister, reg); #endif } - Assembler::Jump inline_add32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg) + Jump inline_add32(TrustedImm32 imm, RegisterID reg) { - return as->branchAdd32(Assembler::Overflow, imm, reg); + return as->branchAdd32(ResultCondition::Overflow, imm, reg); } - Assembler::Jump inline_sub32(Assembler::Address addr, Assembler::RegisterID reg) + Jump inline_sub32(Address addr, RegisterID reg) { #if HAVE(ALU_OPS_WITH_MEM_OPERAND) - return as->branchSub32(Assembler::Overflow, addr, reg); + return as->branchSub32(ResultCondition::Overflow, addr, reg); #else as->load32(addr, Assembler::ScratchRegister); - return as->branchSub32(Assembler::Overflow, Assembler::ScratchRegister, reg); + return as->branchSub32(ResultCondition::Overflow, Assembler::ScratchRegister, reg); #endif } - Assembler::Jump inline_sub32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg) + Jump inline_sub32(TrustedImm32 imm, RegisterID reg) { - return as->branchSub32(Assembler::Overflow, imm, reg); + return as->branchSub32(ResultCondition::Overflow, imm, reg); } - Assembler::Jump inline_mul32(Assembler::Address addr, Assembler::RegisterID reg) + Jump inline_mul32(Address addr, RegisterID reg) { #if HAVE(ALU_OPS_WITH_MEM_OPERAND) return as->branchMul32(Assembler::Overflow, addr, reg); #else as->load32(addr, Assembler::ScratchRegister); - return as->branchMul32(Assembler::Overflow, Assembler::ScratchRegister, reg); + return as->branchMul32(ResultCondition::Overflow, Assembler::ScratchRegister, reg); #endif } - Assembler::Jump inline_mul32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg) + Jump inline_mul32(TrustedImm32 imm, RegisterID reg) { - return as->branchMul32(Assembler::Overflow, imm, reg, reg); + return as->branchMul32(ResultCondition::Overflow, imm, reg, reg); } - Assembler::Jump inline_shl32(Assembler::Address addr, Assembler::RegisterID reg) + Jump inline_shl32(Address addr, RegisterID reg) { as->load32(addr, Assembler::ScratchRegister); - as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister); + as->and32(TrustedImm32(0x1f), Assembler::ScratchRegister); as->lshift32(Assembler::ScratchRegister, reg); - return Assembler::Jump(); + return Jump(); } - Assembler::Jump inline_shl32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg) + Jump inline_shl32(TrustedImm32 imm, RegisterID reg) { imm.m_value &= 0x1f; as->lshift32(imm, reg); - return Assembler::Jump(); + return Jump(); } - Assembler::Jump inline_shr32(Assembler::Address addr, Assembler::RegisterID reg) + Jump inline_shr32(Address addr, RegisterID reg) { as->load32(addr, Assembler::ScratchRegister); - as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister); + as->and32(TrustedImm32(0x1f), Assembler::ScratchRegister); as->rshift32(Assembler::ScratchRegister, reg); - return Assembler::Jump(); + return Jump(); } - Assembler::Jump inline_shr32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg) + Jump inline_shr32(TrustedImm32 imm, RegisterID reg) { imm.m_value &= 0x1f; as->rshift32(imm, reg); - return Assembler::Jump(); + return Jump(); } - Assembler::Jump inline_ushr32(Assembler::Address addr, Assembler::RegisterID reg) + Jump inline_ushr32(Address addr, RegisterID reg) { as->load32(addr, Assembler::ScratchRegister); - as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister); + as->and32(TrustedImm32(0x1f), Assembler::ScratchRegister); as->urshift32(Assembler::ScratchRegister, reg); - return as->branchTest32(Assembler::Signed, reg, reg); + return as->branchTest32(ResultCondition::Signed, reg, reg); } - Assembler::Jump inline_ushr32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg) + Jump inline_ushr32(TrustedImm32 imm, RegisterID reg) { imm.m_value &= 0x1f; as->urshift32(imm, reg); - return as->branchTest32(Assembler::Signed, reg, reg); + return as->branchTest32(ResultCondition::Signed, reg, reg); } - Assembler::Jump inline_and32(Assembler::Address addr, Assembler::RegisterID reg) + Jump inline_and32(Address addr, RegisterID reg) { #if HAVE(ALU_OPS_WITH_MEM_OPERAND) as->and32(addr, reg); @@ -186,16 +196,16 @@ struct Binop { as->load32(addr, Assembler::ScratchRegister); as->and32(Assembler::ScratchRegister, reg); #endif - return Assembler::Jump(); + return Jump(); } - Assembler::Jump inline_and32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg) + Jump inline_and32(TrustedImm32 imm, RegisterID reg) { as->and32(imm, reg); - return Assembler::Jump(); + return Jump(); } - Assembler::Jump inline_or32(Assembler::Address addr, Assembler::RegisterID reg) + Jump inline_or32(Address addr, RegisterID reg) { #if HAVE(ALU_OPS_WITH_MEM_OPERAND) as->or32(addr, reg); @@ -203,16 +213,16 @@ struct Binop { as->load32(addr, Assembler::ScratchRegister); as->or32(Assembler::ScratchRegister, reg); #endif - return Assembler::Jump(); + return Jump(); } - Assembler::Jump inline_or32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg) + Jump inline_or32(TrustedImm32 imm, RegisterID reg) { as->or32(imm, reg); - return Assembler::Jump(); + return Jump(); } - Assembler::Jump inline_xor32(Assembler::Address addr, Assembler::RegisterID reg) + Jump inline_xor32(Address addr, RegisterID reg) { #if HAVE(ALU_OPS_WITH_MEM_OPERAND) as->xor32(addr, reg); @@ -220,13 +230,13 @@ struct Binop { as->load32(addr, Assembler::ScratchRegister); as->xor32(Assembler::ScratchRegister, reg); #endif - return Assembler::Jump(); + return Jump(); } - Assembler::Jump inline_xor32(Assembler::TrustedImm32 imm, Assembler::RegisterID reg) + Jump inline_xor32(TrustedImm32 imm, RegisterID reg) { as->xor32(imm, reg); - return Assembler::Jump(); + return Jump(); } -- cgit v1.2.3 From 5a5f140e60a65ae9a976444c1e47e5a8c606ff21 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Thu, 5 Jan 2017 20:19:18 +0100 Subject: QQmlInfo: Add qmlDebug & qmlWarning functions alongside qmlInfo This way, we can correctly write to multiple levels of QDebug with QML context information. A followup change will port all existing callers, and subsequently change qmlInfo's message level to QtInfoMsg. [ChangeLog][QtQml] Introduced qmlDebug & qmlWarning functions to qqmlinfo.h, in addition to the pre-existing qmlInfo function. As a side effect, QQmlError has also gained messageType() and setMessageType(). Change-Id: I04ced5952c5c3c58293a89a6767c7b545c03cc0a Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlengine.cpp | 26 ++++++- src/qml/qml/qqmlerror.cpp | 27 ++++++- src/qml/qml/qqmlerror.h | 3 + src/qml/qml/qqmlinfo.cpp | 127 +++++++++++++++++++++++++------ src/qml/qml/qqmlinfo.h | 16 +++- tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp | 14 ++++ 6 files changed, 185 insertions(+), 28 deletions(-) diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index c2915c840b..3a95d353f5 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1914,9 +1914,29 @@ void QQmlEnginePrivate::sendExit(int retCode) static void dumpwarning(const QQmlError &error) { - QMessageLogger(error.url().toString().toLatin1().constData(), - error.line(), 0).warning().nospace() - << qPrintable(error.toString()); + switch (error.messageType()) { + case QtDebugMsg: + QMessageLogger(error.url().toString().toLatin1().constData(), + error.line(), 0).debug().nospace() + << qPrintable(error.toString()); + break; + case QtInfoMsg: + QMessageLogger(error.url().toString().toLatin1().constData(), + error.line(), 0).info().nospace() + << qPrintable(error.toString()); + break; + case QtWarningMsg: + case QtFatalMsg: // fatal does not support streaming, and furthermore, is actually fatal. Probably not desirable for QML. + QMessageLogger(error.url().toString().toLatin1().constData(), + error.line(), 0).warning().nospace() + << qPrintable(error.toString()); + break; + case QtCriticalMsg: + QMessageLogger(error.url().toString().toLatin1().constData(), + error.line(), 0).critical().nospace() + << qPrintable(error.toString()); + break; + } } static void dumpwarning(const QList &errors) diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp index 0a6c7b4960..0cb82cdbd9 100644 --- a/src/qml/qml/qqmlerror.cpp +++ b/src/qml/qml/qqmlerror.cpp @@ -85,11 +85,12 @@ public: QString description; quint16 line; quint16 column; + QtMsgType messageType; QObject *object; }; QQmlErrorPrivate::QQmlErrorPrivate() -: line(0), column(0), object() +: line(0), column(0), messageType(QtMsgType::QtWarningMsg), object() { } @@ -125,6 +126,7 @@ QQmlError &QQmlError::operator=(const QQmlError &other) d->line = other.d->line; d->column = other.d->column; d->object = other.d->object; + d->messageType = other.d->messageType; } return *this; } @@ -238,6 +240,29 @@ void QQmlError::setObject(QObject *object) d->object = object; } +/*! + \since 5.9 + + Returns the message type. + */ +QtMsgType QQmlError::messageType() const +{ + if (d) return d->messageType; + else return QtMsgType::QtWarningMsg; +} + +/*! + \since 5.9 + + Sets the \a messageType for this message. The message type determines which + QDebug handlers are responsible for recieving the message. + */ +void QQmlError::setMessageType(QtMsgType messageType) +{ + if (!d) d = new QQmlErrorPrivate; + d->messageType = messageType; +} + /*! Returns the error as a human readable string. */ diff --git a/src/qml/qml/qqmlerror.h b/src/qml/qml/qqmlerror.h index e4c42223cf..ef529e3828 100644 --- a/src/qml/qml/qqmlerror.h +++ b/src/qml/qml/qqmlerror.h @@ -47,6 +47,7 @@ QT_BEGIN_NAMESPACE +// ### Qt 6: should this be called QQmlMessage, since it can have a message type? class QDebug; class QQmlErrorPrivate; class Q_QML_EXPORT QQmlError @@ -69,6 +70,8 @@ public: void setColumn(int); QObject *object() const; void setObject(QObject *); + QtMsgType messageType() const; + void setMessageType(QtMsgType messageType); QString toString() const; private: diff --git a/src/qml/qml/qqmlinfo.cpp b/src/qml/qml/qqmlinfo.cpp index 5b6e02d5b1..e87f29753a 100644 --- a/src/qml/qml/qqmlinfo.cpp +++ b/src/qml/qml/qqmlinfo.cpp @@ -49,14 +49,46 @@ QT_BEGIN_NAMESPACE +/*! + \fn QQmlInfo QtQml::qmlDebug(const QObject *object) + \relates QQmlEngine + \since 5.9 + + Prints debug messages that include the file and line number for the + specified QML \a object. + + When QML types produce logging messages, it improves traceability + if they include the QML file and line number on which the + particular instance was instantiated. + + To include the file and line number, an object must be passed. If + the file and line number is not available for that instance + (either it was not instantiated by the QML engine or location + information is disabled), "unknown location" will be used instead. + + For example, + + \code + qmlDebug(object) << "Internal state: 42"; + \endcode + + prints + + \code + QML MyCustomType (unknown location): Internal state: 42 + \endcode + + \sa QtQml::qmlInfo, QtQml::qmlWarning +*/ + /*! \fn QQmlInfo QtQml::qmlInfo(const QObject *object) \relates QQmlEngine - Prints warning messages that include the file and line number for the + Prints informational messages that include the file and line number for the specified QML \a object. - When QML types display warning messages, it improves traceability + When QML types produce logging messages, it improves traceability if they include the QML file and line number on which the particular instance was instantiated. @@ -76,14 +108,58 @@ QT_BEGIN_NAMESPACE \code QML MyCustomType (unknown location): component property is a write-once property \endcode + + \note In versions prior to Qt 5.9, qmlInfo reported messages using a warning + QtMsgType. For Qt 5.9 and above, qmlInfo uses an info QtMsgType. To send + warnings, use qmlWarning. + + \sa QtQml::qmlDebug, QtQml::qmlWarning +*/ + + +/*! + \fn QQmlInfo QtQml::qmlWarning(const QObject *object) + \relates QQmlEngine + \since 5.9 + + Prints warning messages that include the file and line number for the + specified QML \a object. + + When QML types produce logging messages, it improves traceability + if they include the QML file and line number on which the + particular instance was instantiated. + + To include the file and line number, an object must be passed. If + the file and line number is not available for that instance + (either it was not instantiated by the QML engine or location + information is disabled), "unknown location" will be used instead. + + For example, + + \code + qmlInfo(object) << tr("property cannot be set to 0"); + \endcode + + prints + + \code + QML MyCustomType (unknown location): property cannot be set to 0 + \endcode + + \sa QtQml::qmlDebug, QtQml::qmlInfo */ class QQmlInfoPrivate { public: - QQmlInfoPrivate() : ref (1), object(0) {} + QQmlInfoPrivate(QtMsgType type) + : ref (1) + , msgType(type) + , object(nullptr) + {} int ref; + QtMsgType msgType; const QObject *object; QString buffer; QList errors; @@ -110,6 +186,7 @@ QQmlInfo::~QQmlInfo() if (!d->buffer.isEmpty()) { QQmlError error; + error.setMessageType(d->msgType); QObject *object = const_cast(d->object); @@ -139,28 +216,32 @@ QQmlInfo::~QQmlInfo() namespace QtQml { -QQmlInfo qmlInfo(const QObject *me) -{ - QQmlInfoPrivate *d = new QQmlInfoPrivate; - d->object = me; - return QQmlInfo(d); -} +#define MESSAGE_FUNCS(FuncName, MessageLevel) \ + QQmlInfo FuncName(const QObject *me) \ + { \ + QQmlInfoPrivate *d = new QQmlInfoPrivate(MessageLevel); \ + d->object = me; \ + return QQmlInfo(d); \ + } \ + QQmlInfo FuncName(const QObject *me, const QQmlError &error) \ + { \ + QQmlInfoPrivate *d = new QQmlInfoPrivate(MessageLevel); \ + d->object = me; \ + d->errors << error; \ + return QQmlInfo(d); \ + } \ + QQmlInfo FuncName(const QObject *me, const QList &errors) \ + { \ + QQmlInfoPrivate *d = new QQmlInfoPrivate(MessageLevel); \ + d->object = me; \ + d->errors = errors; \ + return QQmlInfo(d); \ + } -QQmlInfo qmlInfo(const QObject *me, const QQmlError &error) -{ - QQmlInfoPrivate *d = new QQmlInfoPrivate; - d->object = me; - d->errors << error; - return QQmlInfo(d); -} +MESSAGE_FUNCS(qmlDebug, QtMsgType::QtDebugMsg) +MESSAGE_FUNCS(qmlInfo, QtMsgType::QtWarningMsg) // XXX: temporary, switch to QtInfoMsg when callers are ported +MESSAGE_FUNCS(qmlWarning, QtMsgType::QtWarningMsg) -QQmlInfo qmlInfo(const QObject *me, const QList &errors) -{ - QQmlInfoPrivate *d = new QQmlInfoPrivate; - d->object = me; - d->errors = errors; - return QQmlInfo(d); -} } // namespace QtQml diff --git a/src/qml/qml/qqmlinfo.h b/src/qml/qml/qqmlinfo.h index ab0281a688..673125632e 100644 --- a/src/qml/qml/qqmlinfo.h +++ b/src/qml/qml/qqmlinfo.h @@ -48,11 +48,19 @@ QT_BEGIN_NAMESPACE class QQmlInfo; +// declared in namespace to avoid symbol conflicts with QtDeclarative namespace QtQml { - // declared in namespace to avoid symbol conflicts with QtDeclarative + Q_QML_EXPORT QQmlInfo qmlDebug(const QObject *me); + Q_QML_EXPORT QQmlInfo qmlDebug(const QObject *me, const QQmlError &error); + Q_QML_EXPORT QQmlInfo qmlDebug(const QObject *me, const QList &errors); + Q_QML_EXPORT QQmlInfo qmlInfo(const QObject *me); Q_QML_EXPORT QQmlInfo qmlInfo(const QObject *me, const QQmlError &error); Q_QML_EXPORT QQmlInfo qmlInfo(const QObject *me, const QList &errors); + + Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me); + Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me, const QQmlError &error); + Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me, const QList &errors); } QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wheader-hygiene") @@ -93,9 +101,15 @@ public: #endif private: + friend Q_QML_EXPORT QQmlInfo QtQml::qmlDebug(const QObject *me); + friend Q_QML_EXPORT QQmlInfo QtQml::qmlDebug(const QObject *me, const QQmlError &error); + friend Q_QML_EXPORT QQmlInfo QtQml::qmlDebug(const QObject *me, const QList &errors); friend Q_QML_EXPORT QQmlInfo QtQml::qmlInfo(const QObject *me); friend Q_QML_EXPORT QQmlInfo QtQml::qmlInfo(const QObject *me, const QQmlError &error); friend Q_QML_EXPORT QQmlInfo QtQml::qmlInfo(const QObject *me, const QList &errors); + friend Q_QML_EXPORT QQmlInfo QtQml::qmlWarning(const QObject *me); + friend Q_QML_EXPORT QQmlInfo QtQml::qmlWarning(const QObject *me, const QQmlError &error); + friend Q_QML_EXPORT QQmlInfo QtQml::qmlWarning(const QObject *me, const QList &errors); QQmlInfo(QQmlInfoPrivate *); QQmlInfoPrivate *d; diff --git a/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp b/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp index acda06c8d8..ce3004a31c 100644 --- a/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp +++ b/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp @@ -49,6 +49,7 @@ private slots: void nonQmlContextedObject(); void types(); void chaining(); + void messageTypes(); private: QQmlEngine engine; @@ -202,6 +203,19 @@ void tst_qqmlinfo::chaining() << QUrl("http://www.qt-project.org"); } +// Ensure that messages of different types are sent with the correct QtMsgType. +void tst_qqmlinfo::messageTypes() +{ + QTest::ignoreMessage(QtDebugMsg, ": debug"); + qmlDebug(0) << QLatin1String("debug"); + + QTest::ignoreMessage(QtWarningMsg, ": info"); + qmlInfo(0) << QLatin1String("info"); + + QTest::ignoreMessage(QtWarningMsg, ": warning"); + qmlWarning(0) << QLatin1String("warning"); +} + QTEST_MAIN(tst_qqmlinfo) #include "tst_qqmlinfo.moc" -- cgit v1.2.3 From b7260709d4da805696d2c7676cdda2d5295e667f Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Thu, 5 Jan 2017 20:19:25 +0100 Subject: QQmlError: Fix code style a bit Don't use single-line if, they are rather error prone, and remove (equally error-prone) superfluous else. Change-Id: If397de42d6c8820ac80125ca3a275572c841f257 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlerror.cpp | 51 +++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp index 0cb82cdbd9..7a1e02eec6 100644 --- a/src/qml/qml/qqmlerror.cpp +++ b/src/qml/qml/qqmlerror.cpp @@ -120,7 +120,8 @@ QQmlError &QQmlError::operator=(const QQmlError &other) delete d; d = 0; } else { - if (!d) d = new QQmlErrorPrivate; + if (!d) + d = new QQmlErrorPrivate; d->url = other.d->url; d->description = other.d->description; d->line = other.d->line; @@ -152,8 +153,9 @@ bool QQmlError::isValid() const */ QUrl QQmlError::url() const { - if (d) return d->url; - else return QUrl(); + if (d) + return d->url; + return QUrl(); } /*! @@ -161,7 +163,8 @@ QUrl QQmlError::url() const */ void QQmlError::setUrl(const QUrl &url) { - if (!d) d = new QQmlErrorPrivate; + if (!d) + d = new QQmlErrorPrivate; d->url = url; } @@ -170,8 +173,9 @@ void QQmlError::setUrl(const QUrl &url) */ QString QQmlError::description() const { - if (d) return d->description; - else return QString(); + if (d) + return d->description; + return QString(); } /*! @@ -179,7 +183,8 @@ QString QQmlError::description() const */ void QQmlError::setDescription(const QString &description) { - if (!d) d = new QQmlErrorPrivate; + if (!d) + d = new QQmlErrorPrivate; d->description = description; } @@ -188,8 +193,9 @@ void QQmlError::setDescription(const QString &description) */ int QQmlError::line() const { - if (d) return qmlSourceCoordinate(d->line); - else return -1; + if (d) + return qmlSourceCoordinate(d->line); + return -1; } /*! @@ -197,7 +203,8 @@ int QQmlError::line() const */ void QQmlError::setLine(int line) { - if (!d) d = new QQmlErrorPrivate; + if (!d) + d = new QQmlErrorPrivate; d->line = qmlSourceCoordinate(line); } @@ -206,8 +213,9 @@ void QQmlError::setLine(int line) */ int QQmlError::column() const { - if (d) return qmlSourceCoordinate(d->column); - else return -1; + if (d) + return qmlSourceCoordinate(d->column); + return -1; } /*! @@ -215,7 +223,8 @@ int QQmlError::column() const */ void QQmlError::setColumn(int column) { - if (!d) d = new QQmlErrorPrivate; + if (!d) + d = new QQmlErrorPrivate; d->column = qmlSourceCoordinate(column); } @@ -227,8 +236,9 @@ void QQmlError::setColumn(int column) */ QObject *QQmlError::object() const { - if (d) return d->object; - else return 0; + if (d) + return d->object; + return 0; } /*! @@ -236,7 +246,8 @@ QObject *QQmlError::object() const */ void QQmlError::setObject(QObject *object) { - if (!d) d = new QQmlErrorPrivate; + if (!d) + d = new QQmlErrorPrivate; d->object = object; } @@ -247,8 +258,9 @@ void QQmlError::setObject(QObject *object) */ QtMsgType QQmlError::messageType() const { - if (d) return d->messageType; - else return QtMsgType::QtWarningMsg; + if (d) + return d->messageType; + return QtMsgType::QtWarningMsg; } /*! @@ -259,7 +271,8 @@ QtMsgType QQmlError::messageType() const */ void QQmlError::setMessageType(QtMsgType messageType) { - if (!d) d = new QQmlErrorPrivate; + if (!d) + d = new QQmlErrorPrivate; d->messageType = messageType; } -- cgit v1.2.3 From 0252d05d06f450b2f2783c905c424d24725fc70a Mon Sep 17 00:00:00 2001 From: Oleg Yadrov Date: Wed, 28 Dec 2016 14:40:11 -0800 Subject: PathView: fix crash on path remove There was no check if new path is a valid object Task-number: QTBUG-53917 Change-Id: I2fd9534c1d34633243d16eda56a2b07e18dabe16 Reviewed-by: Laszlo Agocs Reviewed-by: Shawn Rutledge Reviewed-by: Robin Burchell --- src/quick/items/qquickpathview.cpp | 21 +++++++++++------ .../auto/quick/qquickpathview/data/removePath.qml | 26 ++++++++++++++++++++++ .../quick/qquickpathview/tst_qquickpathview.cpp | 14 ++++++++++++ 3 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 tests/auto/quick/qquickpathview/data/removePath.qml diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index 11881ae0ab..03596f13e9 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -704,16 +704,23 @@ void QQuickPathView::setPath(QQuickPath *path) qmlobject_disconnect(d->path, QQuickPath, SIGNAL(changed()), this, QQuickPathView, SLOT(pathUpdated())); d->path = path; - qmlobject_connect(d->path, QQuickPath, SIGNAL(changed()), - this, QQuickPathView, SLOT(pathUpdated())); - if (d->isValid() && isComponentComplete()) { + + if (path) { + qmlobject_connect(d->path, QQuickPath, SIGNAL(changed()), + this, QQuickPathView, SLOT(pathUpdated())); + } + + if (isComponentComplete()) { d->clear(); - if (d->attType) { - d->attType->release(); - d->attType = nullptr; + if (d->isValid()) { + if (d->attType) { + d->attType->release(); + d->attType = nullptr; + } + d->regenerate(); } - d->regenerate(); } + emit pathChanged(); } diff --git a/tests/auto/quick/qquickpathview/data/removePath.qml b/tests/auto/quick/qquickpathview/data/removePath.qml new file mode 100644 index 0000000000..85029f3eaf --- /dev/null +++ b/tests/auto/quick/qquickpathview/data/removePath.qml @@ -0,0 +1,26 @@ +import QtQuick 2.0 + +PathView { + width: 240 + height: 200 + + path: myPath + + delegate: Text { text: value } + model: 10 + + Path { + id: myPath + startX: 120; startY: 100 + PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 } + PathQuad { x: 120; y: 100; controlX: -20; controlY: 75 } + } + + function removePath() { + path = null + } + + function setPath() { + path = myPath + } +} diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp index ba3d182efc..b01d0c3cec 100644 --- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp +++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp @@ -141,6 +141,7 @@ private slots: void addCustomAttribute(); void movementDirection_data(); void movementDirection(); + void removePath(); }; class TestObject : public QObject @@ -2504,6 +2505,19 @@ void tst_QQuickPathView::movementDirection() verify_offsets(pathview, toidx, fromoffset, tooffset); } +void tst_QQuickPathView::removePath() +{ + QScopedPointer window(createView()); + window->setSource(testFileUrl("removePath.qml")); + window->show(); + + QQuickPathView *pathview = qobject_cast(window->rootObject()); + QVERIFY(pathview != 0); + + QVERIFY(QMetaObject::invokeMethod(pathview, "removePath")); + QVERIFY(QMetaObject::invokeMethod(pathview, "setPath")); +} + QTEST_MAIN(tst_QQuickPathView) #include "tst_qquickpathview.moc" -- cgit v1.2.3 From 3294d1b291ebd52eb967c7cdb2081ce4e594ad89 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 11 Jan 2017 16:40:28 +0100 Subject: tst_touchmouse: Have a go at some stabilisation & improvements * Use QScopedPointer to own views, preventing leakage (was a problem in a few of these tests, e.g. pinchOnFlickable/flickableOnPinch/mouseOnFlickableOnPinch) * Only qWaitForWindowActive, as the tests aren't doing anything graphical, they don't need an expose event, which means less waiting * Use the test utilities to center the windows on screen to make sure they are not under desktop chrome & have a non-null position. If position is 0,0 that means window->position().isNull() is true, so qWaitForWindowActive will wait for its entire timeout: 5 seconds. This means no "manual" tweaking of geometry anymore: the position is now taken care of by the test utilities, and we let the root QML item size determine the window size. * Move the mouse away from the window using the test utilities. Done-with: Shawn Rutledge Change-Id: I4ac6a0d56067c57ef51f186fe3cd118cab056ff2 Reviewed-by: Shawn Rutledge --- tests/auto/quick/touchmouse/tst_touchmouse.cpp | 585 ++++++++++++------------- 1 file changed, 270 insertions(+), 315 deletions(-) diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp index b5af61d723..4f4fac8fa5 100644 --- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp +++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp @@ -194,8 +194,6 @@ private: QQuickView *tst_TouchMouse::createView() { QQuickView *window = new QQuickView(0); - window->setGeometry(0,0,240,320); - return window; } @@ -210,13 +208,11 @@ void tst_TouchMouse::initTestCase() void tst_TouchMouse::simpleTouchEvent() { - QQuickView *window = createView(); - + QScopedPointer window(createView()); window->setSource(testFileUrl("singleitem.qml")); window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - window->requestActivate(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QQuickViewTestUtil::centerOnScreen(window.data()); + QVERIFY(QTest::qWaitForWindowActive(window.data())); QVERIFY(window->rootObject() != 0); EventItem *eventItem1 = window->rootObject()->findChild("eventItem1"); @@ -225,33 +221,33 @@ void tst_TouchMouse::simpleTouchEvent() // Do not accept touch or mouse QPoint p1; p1 = QPoint(20, 20); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); // Get a touch and then mouse event offered QCOMPARE(eventItem1->eventList.size(), 2); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); p1 += QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); // Not accepted, no updates QCOMPARE(eventItem1->eventList.size(), 2); - QTest::touchEvent(window, device).release(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).release(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 2); eventItem1->eventList.clear(); // Accept touch eventItem1->acceptTouch = true; p1 = QPoint(20, 20); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 1); p1 += QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 2); - QTest::touchEvent(window, device).release(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).release(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 3); eventItem1->eventList.clear(); @@ -263,8 +259,8 @@ void tst_TouchMouse::simpleTouchEvent() eventItem1->acceptMouse = true; eventItem1->setAcceptedMouseButtons(Qt::LeftButton); p1 = QPoint(20, 20); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 2); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); @@ -280,13 +276,13 @@ void tst_TouchMouse::simpleTouchEvent() QCOMPARE(eventItem1->eventList.at(1).mousePosGlobal, globalPos); p1 += QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 4); QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate); QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove); - QTest::touchEvent(window, device).release(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).release(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 7); QCOMPARE(eventItem1->eventList.at(4).type, QEvent::TouchEnd); QCOMPARE(eventItem1->eventList.at(5).type, QEvent::MouseButtonRelease); @@ -301,17 +297,17 @@ void tst_TouchMouse::simpleTouchEvent() eventItem1->acceptMouse = false; eventItem1->setAcceptedMouseButtons(Qt::LeftButton); p1 = QPoint(20, 20); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 2); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); p1 += QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 2); - QTest::touchEvent(window, device).release(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).release(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 2); eventItem1->eventList.clear(); @@ -322,32 +318,30 @@ void tst_TouchMouse::simpleTouchEvent() eventItem1->acceptTouch = true; eventItem1->setAcceptedMouseButtons(Qt::LeftButton); p1 = QPoint(20, 20); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 1); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); p1 += QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 2); QCOMPARE(eventItem1->eventList.at(1).type, QEvent::TouchUpdate); - QTest::touchEvent(window, device).release(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).release(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 3); QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd); eventItem1->eventList.clear(); - - delete window; } void tst_TouchMouse::testEventFilter() { // // install event filter on item and see that it can grab events -// QQuickView *window = createView(); - +// QScopedPointer window(createView()); // window->setSource(testFileUrl("singleitem.qml")); // window->show(); -// window->requestActivate(); +// QQuickViewTestUtil::centerOnScreen(window.data()); +// QVERIFY(QTest::qWaitForWindowActive(window.data())); // QVERIFY(window->rootObject() != 0); // EventItem *eventItem1 = window->rootObject()->findChild("eventItem1"); @@ -359,16 +353,15 @@ void tst_TouchMouse::testEventFilter() // eventItem1->installEventFilter(filter); // QPoint p1 = QPoint(20, 20); -// QTest::touchEvent(window, device).press(0, p1, window); +// QTest::touchEvent(window.data(), device).press(0, p1, window.data()); // // QEXPECT_FAIL("", "We do not implement event filters correctly", Abort); // QCOMPARE(eventItem1->eventList.size(), 0); // QCOMPARE(filter->eventList.size(), 1); -// QTest::touchEvent(window, device).release(0, p1, window); +// QTest::touchEvent(window.data(), device).release(0, p1, window.data()); // QCOMPARE(eventItem1->eventList.size(), 0); // QCOMPARE(filter->eventList.size(), 2); // delete filter; -// delete window; } void tst_TouchMouse::mouse() @@ -377,34 +370,29 @@ void tst_TouchMouse::mouse() // - eventItem2 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); - QQuickView *window = createView(); - + QScopedPointer window(createView()); window->setSource(testFileUrl("twoitems.qml")); window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - window->requestActivate(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QQuickViewTestUtil::centerOnScreen(window.data()); + QVERIFY(QTest::qWaitForWindowActive(window.data())); QVERIFY(window->rootObject() != 0); EventItem *eventItem1 = window->rootObject()->findChild("eventItem1"); QVERIFY(eventItem1); EventItem *eventItem2 = window->rootObject()->findChild("eventItem2"); QVERIFY(eventItem2); - QVERIFY(QTest::qWaitForWindowExposed(window)); // bottom item likes mouse, top likes touch eventItem1->setAcceptedMouseButtons(Qt::LeftButton); eventItem1->acceptMouse = true; // item 2 doesn't accept anything, thus it sees a touch pass by QPoint p1 = QPoint(30, 30); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 2); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); - - delete window; } void tst_TouchMouse::touchOverMouse() @@ -412,13 +400,11 @@ void tst_TouchMouse::touchOverMouse() // eventItem1 // - eventItem2 - QQuickView *window = createView(); - + QScopedPointer window(createView()); window->setSource(testFileUrl("twoitems.qml")); window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - window->requestActivate(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QQuickViewTestUtil::centerOnScreen(window.data()); + QVERIFY(QTest::qWaitForWindowActive(window.data())); QVERIFY(window->rootObject() != 0); EventItem *eventItem1 = window->rootObject()->findChild("eventItem1"); @@ -430,27 +416,23 @@ void tst_TouchMouse::touchOverMouse() eventItem1->setAcceptedMouseButtons(Qt::LeftButton); eventItem2->acceptTouch = true; - QVERIFY(QTest::qWaitForWindowExposed(window)); - QCOMPARE(eventItem1->eventList.size(), 0); QPoint p1 = QPoint(20, 20); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 0); QCOMPARE(eventItem2->eventList.size(), 1); QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin); p1 += QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem2->eventList.size(), 2); QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchUpdate); - QTest::touchEvent(window, device).release(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).release(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem2->eventList.size(), 3); QCOMPARE(eventItem2->eventList.at(2).type, QEvent::TouchEnd); eventItem2->eventList.clear(); - - delete window; } void tst_TouchMouse::mouseOverTouch() @@ -458,13 +440,11 @@ void tst_TouchMouse::mouseOverTouch() // eventItem1 // - eventItem2 - QQuickView *window = createView(); - + QScopedPointer window(createView()); window->setSource(testFileUrl("twoitems.qml")); window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - window->requestActivate(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QQuickViewTestUtil::centerOnScreen(window.data()); + QVERIFY(QTest::qWaitForWindowActive(window.data())); QVERIFY(window->rootObject() != 0); EventItem *eventItem1 = window->rootObject()->findChild("eventItem1"); @@ -477,12 +457,10 @@ void tst_TouchMouse::mouseOverTouch() eventItem2->setAcceptedMouseButtons(Qt::LeftButton); eventItem2->acceptMouse = true; - QVERIFY(QTest::qWaitForWindowExposed(window)); - QPoint p1 = QPoint(20, 20); QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 0); QCOMPARE(eventItem2->eventList.size(), 2); QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin); @@ -490,13 +468,11 @@ void tst_TouchMouse::mouseOverTouch() // p1 += QPoint(10, 0); -// QTest::touchEvent(window, device).move(0, p1, window); +// QTest::touchEvent(window.data(), device).move(0, p1, window.data()); // QCOMPARE(eventItem2->eventList.size(), 1); -// QTest::touchEvent(window, device).release(0, p1, window); +// QTest::touchEvent(window.data(), device).release(0, p1, window.data()); // QCOMPARE(eventItem2->eventList.size(), 1); // eventItem2->eventList.clear(); - - delete window; } void tst_TouchMouse::buttonOnFlickable() @@ -505,13 +481,11 @@ void tst_TouchMouse::buttonOnFlickable() // - eventItem1 y: 100, height 100 // - eventItem2 y: 300, height 100 - QQuickView *window = createView(); - + QScopedPointer window(createView()); window->setSource(testFileUrl("buttononflickable.qml")); window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - window->requestActivate(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QQuickViewTestUtil::centerOnScreen(window.data()); + QVERIFY(QTest::qWaitForWindowActive(window.data())); QVERIFY(window->rootObject() != 0); QQuickFlickable *flickable = window->rootObject()->findChild("flickable"); @@ -536,13 +510,13 @@ void tst_TouchMouse::buttonOnFlickable() // mouse button QCOMPARE(eventItem1->eventList.size(), 0); QPoint p1 = QPoint(20, 130); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QTRY_COMPARE(eventItem1->eventList.size(), 2); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); - QTest::touchEvent(window, device).release(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).release(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 5); QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd); QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseButtonRelease); @@ -551,12 +525,12 @@ void tst_TouchMouse::buttonOnFlickable() // touch button p1 = QPoint(10, 310); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem2->eventList.size(), 1); QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin); - QTest::touchEvent(window, device).release(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).release(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem2->eventList.size(), 2); QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchEnd); QCOMPARE(eventItem1->eventList.size(), 0); @@ -567,11 +541,11 @@ void tst_TouchMouse::buttonOnFlickable() // click above button, no events please p1 = QPoint(10, 90); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 0); - QTest::touchEvent(window, device).release(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).release(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 0); eventItem1->eventList.clear(); @@ -581,13 +555,13 @@ void tst_TouchMouse::buttonOnFlickable() // check that flickable moves - mouse button QCOMPARE(eventItem1->eventList.size(), 0); p1 = QPoint(10, 110); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 2); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); - QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window); + QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window.data()); QVERIFY(windowPriv->touchMouseId != -1); auto pointerEvent = QQuickPointerDevice::touchDevices().at(0)->pointerEvent(); QCOMPARE(pointerEvent->point(0)->grabber(), eventItem1); @@ -596,13 +570,13 @@ void tst_TouchMouse::buttonOnFlickable() p1 += QPoint(0, -10); QPoint p2 = p1 + QPoint(0, -10); QPoint p3 = p2 + QPoint(0, -10); - QQuickTouchUtils::flush(window); - QTest::touchEvent(window, device).move(0, p1, window); - QQuickTouchUtils::flush(window); - QTest::touchEvent(window, device).move(0, p2, window); - QQuickTouchUtils::flush(window); - QTest::touchEvent(window, device).move(0, p3, window); - QQuickTouchUtils::flush(window); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).move(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).move(0, p2, window.data()); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).move(0, p3, window.data()); + QQuickTouchUtils::flush(window.data()); // we cannot really know when the events get grabbed away QVERIFY(eventItem1->eventList.size() >= 4); @@ -614,9 +588,8 @@ void tst_TouchMouse::buttonOnFlickable() QCOMPARE(pointerEvent->point(0)->grabber(), flickable); QVERIFY(flickable->isMovingVertically()); - QTest::touchEvent(window, device).release(0, p3, window); - QQuickTouchUtils::flush(window); - delete window; + QTest::touchEvent(window.data(), device).release(0, p3, window.data()); + QQuickTouchUtils::flush(window.data()); } void tst_TouchMouse::buttonOnDelayedPressFlickable_data() @@ -642,13 +615,11 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable() qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, true); filteredEventList.clear(); - QQuickView *window = createView(); - + QScopedPointer window(createView()); window->setSource(testFileUrl("buttononflickable.qml")); window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - window->requestActivate(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QQuickViewTestUtil::centerOnScreen(window.data()); + QVERIFY(QTest::qWaitForWindowActive(window.data())); QVERIFY(window->rootObject() != 0); QQuickFlickable *flickable = window->rootObject()->findChild("flickable"); @@ -673,13 +644,13 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable() // wait to avoid getting a double click event QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); - QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window); + QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window.data()); QCOMPARE(windowPriv->touchMouseId, -1); // no grabber // touch press QPoint p1 = QPoint(10, 110); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); if (scrollBeforeDelayIsOver) { // no events, the flickable got scrolled, the button sees nothing @@ -694,13 +665,13 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable() p1 += QPoint(0, -10); QPoint p2 = p1 + QPoint(0, -10); QPoint p3 = p2 + QPoint(0, -10); - QQuickTouchUtils::flush(window); - QTest::touchEvent(window, device).move(0, p1, window); - QQuickTouchUtils::flush(window); - QTest::touchEvent(window, device).move(0, p2, window); - QQuickTouchUtils::flush(window); - QTest::touchEvent(window, device).move(0, p3, window); - QQuickTouchUtils::flush(window); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).move(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).move(0, p2, window.data()); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).move(0, p3, window.data()); + QQuickTouchUtils::flush(window.data()); QTRY_VERIFY(flickable->isMovingVertically()); if (scrollBeforeDelayIsOver) { @@ -721,8 +692,8 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable() auto pointerEvent = QQuickPointerDevice::touchDevices().at(0)->pointerEvent(); QCOMPARE(pointerEvent->point(0)->grabber(), flickable); - QTest::touchEvent(window, device).release(0, p3, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).release(0, p3, window.data()); + QQuickTouchUtils::flush(window.data()); // We should not have received any synthesised mouse events from Qt gui, // just the delayed press. @@ -730,8 +701,6 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable() QCOMPARE(filteredEventList.count(), 0); else QCOMPARE(filteredEventList.count(), 1); - - delete window; } void tst_TouchMouse::buttonOnTouch() @@ -744,12 +713,11 @@ void tst_TouchMouse::buttonOnTouch() // - eventItem1 y: 100, height 100 // - eventItem2 y: 300, height 100 - QQuickView *window = createView(); + QScopedPointer window(createView()); window->setSource(testFileUrl("buttonontouch.qml")); window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - window->requestActivate(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QQuickViewTestUtil::centerOnScreen(window.data()); + QVERIFY(QTest::qWaitForWindowActive(window.data())); QVERIFY(window->rootObject() != 0); QQuickPinchArea *pinchArea = window->rootObject()->findChild("pincharea"); @@ -779,10 +747,10 @@ void tst_TouchMouse::buttonOnTouch() // Normal touch click QPoint p1 = QPoint(10, 110); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); - QTest::touchEvent(window, device).release(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).release(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(eventItem1->eventList.size(), 5); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); @@ -792,7 +760,7 @@ void tst_TouchMouse::buttonOnTouch() eventItem1->eventList.clear(); // Normal mouse click - QTest::mouseClick(window, Qt::LeftButton, 0, p1); + QTest::mouseClick(window.data(), Qt::LeftButton, 0, p1); QCOMPARE(eventItem1->eventList.size(), 3); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress); QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonRelease); @@ -804,35 +772,35 @@ void tst_TouchMouse::buttonOnTouch() QPoint p2 = QPoint(60, 10); // Start the events after each other - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); - QTest::touchEvent(window, device).stationary(0).press(1, p2, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).stationary(0).press(1, p2, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(button1->scale(), 1.0); // This event seems to be discarded, let's ignore it for now until someone digs into pincharea p1 -= QPoint(10, 0); p2 += QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data()); + QQuickTouchUtils::flush(window.data()); p1 -= QPoint(10, 0); p2 += QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data()); + QQuickTouchUtils::flush(window.data()); // QCOMPARE(button1->scale(), 1.5); qDebug() << "Button scale: " << button1->scale(); p1 -= QPoint(10, 0); p2 += QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data()); + QQuickTouchUtils::flush(window.data()); // QCOMPARE(button1->scale(), 2.0); qDebug() << "Button scale: " << button1->scale(); - QTest::touchEvent(window, device).release(0, p1, window).release(1, p2, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).release(0, p1, window.data()).release(1, p2, window.data()); + QQuickTouchUtils::flush(window.data()); // QVERIFY(eventItem1->eventList.isEmpty()); // QCOMPARE(button1->scale(), 2.0); qDebug() << "Button scale: " << button1->scale(); @@ -845,8 +813,8 @@ void tst_TouchMouse::buttonOnTouch() button1->setScale(1.0); p1 = QPoint(40, 110); p2 = QPoint(60, 110); - QTest::touchEvent(window, device).press(0, p1, window).press(1, p2, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()).press(1, p2, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(button1->scale(), 1.0); QCOMPARE(eventItem1->eventList.count(), 2); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); @@ -855,40 +823,37 @@ void tst_TouchMouse::buttonOnTouch() // This event seems to be discarded, let's ignore it for now until someone digs into pincharea p1 -= QPoint(10, 0); p2 += QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data()); + QQuickTouchUtils::flush(window.data()); p1 -= QPoint(10, 0); p2 += QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data()); + QQuickTouchUtils::flush(window.data()); //QCOMPARE(button1->scale(), 1.5); qDebug() << button1->scale(); p1 -= QPoint(10, 0); p2 += QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p1, window.data()).move(1, p2, window.data()); + QQuickTouchUtils::flush(window.data()); qDebug() << button1->scale(); //QCOMPARE(button1->scale(), 2.0); - QTest::touchEvent(window, device).release(0, p1, window).release(1, p2, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).release(0, p1, window.data()).release(1, p2, window.data()); + QQuickTouchUtils::flush(window.data()); // QCOMPARE(eventItem1->eventList.size(), 99); qDebug() << button1->scale(); //QCOMPARE(button1->scale(), 2.0); - - delete window; } void tst_TouchMouse::pinchOnFlickable() { - QQuickView *window = createView(); + QScopedPointer window(createView()); window->setSource(testFileUrl("pinchonflickable.qml")); window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - window->requestActivate(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QQuickViewTestUtil::centerOnScreen(window.data()); + QVERIFY(QTest::qWaitForWindowActive(window.data())); QVERIFY(window->rootObject() != 0); QQuickPinchArea *pinchArea = window->rootObject()->findChild("pincharea"); @@ -901,23 +866,23 @@ void tst_TouchMouse::pinchOnFlickable() // flickable - single touch point QCOMPARE(flickable->contentX(), 0.0); QPoint p = QPoint(100, 100); - QTest::touchEvent(window, device).press(0, p, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(rect->position(), QPointF(200.0, 200.0)); p -= QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p, window.data()); + QQuickTouchUtils::flush(window.data()); p -= QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p, window.data()); + QQuickTouchUtils::flush(window.data()); p -= QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p, window.data()); + QQuickTouchUtils::flush(window.data()); p -= QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p, window); - QQuickTouchUtils::flush(window); - QTest::touchEvent(window, device).release(0, p, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p, window.data()); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).release(0, p, window.data()); + QQuickTouchUtils::flush(window.data()); QGuiApplication::processEvents(); QTest::qWait(10); @@ -929,48 +894,47 @@ void tst_TouchMouse::pinchOnFlickable() QPoint p1 = QPoint(40, 20); QPoint p2 = QPoint(60, 20); - QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device); - QQuickTouchUtils::flush(window); - pinchSequence.press(0, p1, window).commit(); - QQuickTouchUtils::flush(window); + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window.data(), device); + QQuickTouchUtils::flush(window.data()); + pinchSequence.press(0, p1, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); // In order for the stationary point to remember its previous position, // we have to reuse the same pinchSequence object. Otherwise if we let it // be destroyed and then start a new sequence, point 0 will default to being // stationary at 0, 0, and PinchArea will filter out that touchpoint because // it is outside its bounds. - pinchSequence.stationary(0).press(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.stationary(0).press(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); p1 -= QPoint(10,10); p2 += QPoint(10,10); - pinchSequence.move(0, p1, window).move(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); QCOMPARE(rect->scale(), 1.0); p1 -= QPoint(10, 0); p2 += QPoint(10, 0); - pinchSequence.move(0, p1, window).move(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); p1 -= QPoint(10, 0); p2 += QPoint(10, 0); - pinchSequence.move(0, p1, window).move(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); p1 -= QPoint(10, 0); p2 += QPoint(10, 0); - pinchSequence.move(0, p1, window).move(1, p2, window).commit(); + pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit(); QVERIFY(!flickable->isDragging()); - QQuickTouchUtils::flush(window); - pinchSequence.release(0, p1, window).release(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + QQuickTouchUtils::flush(window.data()); + pinchSequence.release(0, p1, window.data()).release(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); QVERIFY(rect->scale() > 1.0); } void tst_TouchMouse::flickableOnPinch() { - QQuickView *window = createView(); + QScopedPointer window(createView()); window->setSource(testFileUrl("flickableonpinch.qml")); window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - window->requestActivate(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QQuickViewTestUtil::centerOnScreen(window.data()); + QVERIFY(QTest::qWaitForWindowActive(window.data())); QVERIFY(window->rootObject() != 0); QQuickPinchArea *pinchArea = window->rootObject()->findChild("pincharea"); @@ -983,23 +947,23 @@ void tst_TouchMouse::flickableOnPinch() // flickable - single touch point QCOMPARE(flickable->contentX(), 0.0); QPoint p = QPoint(100, 100); - QTest::touchEvent(window, device).press(0, p, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(rect->position(), QPointF(200.0, 200.0)); p -= QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p, window.data()); + QQuickTouchUtils::flush(window.data()); p -= QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p, window.data()); + QQuickTouchUtils::flush(window.data()); QTest::qWait(1000); p -= QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p, window); - QQuickTouchUtils::flush(window); - QTest::touchEvent(window, device).release(0, p, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p, window.data()); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).release(0, p, window.data()); + QQuickTouchUtils::flush(window.data()); QTest::qWait(1000); @@ -1011,45 +975,47 @@ void tst_TouchMouse::flickableOnPinch() // pinch QPoint p1 = QPoint(40, 20); QPoint p2 = QPoint(60, 20); - QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device); - pinchSequence.press(0, p1, window).commit(); - QQuickTouchUtils::flush(window); + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window.data(), device); + pinchSequence.press(0, p1, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); // In order for the stationary point to remember its previous position, // we have to reuse the same pinchSequence object. Otherwise if we let it // be destroyed and then start a new sequence, point 0 will default to being // stationary at 0, 0, and PinchArea will filter out that touchpoint because // it is outside its bounds. - pinchSequence.stationary(0).press(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.stationary(0).press(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); p1 -= QPoint(10,10); p2 += QPoint(10,10); - pinchSequence.move(0, p1, window).move(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); QCOMPARE(rect->scale(), 1.0); p1 -= QPoint(10, 0); p2 += QPoint(10, 0); - pinchSequence.move(0, p1, window).move(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); p1 -= QPoint(10, 0); p2 += QPoint(10, 0); - pinchSequence.move(0, p1, window).move(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); p1 -= QPoint(10, 0); p2 += QPoint(10, 0); - pinchSequence.move(0, p1, window).move(1, p2, window).commit(); - QQuickTouchUtils::flush(window); - pinchSequence.release(0, p1, window).release(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); + pinchSequence.release(0, p1, window.data()).release(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); QVERIFY(rect->scale() > 1.0); } void tst_TouchMouse::mouseOnFlickableOnPinch() { - QQuickView *window = createView(); + QScopedPointer window(createView()); window->setSource(testFileUrl("mouseonflickableonpinch.qml")); window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); + QQuickViewTestUtil::centerOnScreen(window.data()); + QVERIFY(QTest::qWaitForWindowActive(window.data())); QVERIFY(window->rootObject() != 0); + QRect windowRect = QRect(window->position(), window->size()); QCursor::setPos(windowRect.center()); @@ -1063,20 +1029,20 @@ void tst_TouchMouse::mouseOnFlickableOnPinch() // flickable - single touch point QCOMPARE(flickable->contentX(), 0.0); QPoint p = QPoint(100, 100); - QTest::touchEvent(window, device).press(0, p, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(rect->position(), QPointF(200.0, 200.0)); p -= QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p, window.data()); + QQuickTouchUtils::flush(window.data()); p -= QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p, window.data()); + QQuickTouchUtils::flush(window.data()); p -= QPoint(10, 0); - QTest::touchEvent(window, device).move(0, p, window); - QQuickTouchUtils::flush(window); - QTest::touchEvent(window, device).release(0, p, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).move(0, p, window.data()); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).release(0, p, window.data()); + QQuickTouchUtils::flush(window.data()); //QVERIFY(flickable->isMovingHorizontally()); @@ -1087,81 +1053,81 @@ void tst_TouchMouse::mouseOnFlickableOnPinch() // pinch QPoint p1 = QPoint(40, 20); QPoint p2 = QPoint(60, 20); - QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device); - pinchSequence.press(0, p1, window).commit(); - QQuickTouchUtils::flush(window); + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window.data(), device); + pinchSequence.press(0, p1, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); // In order for the stationary point to remember its previous position, // we have to reuse the same pinchSequence object. Otherwise if we let it // be destroyed and then start a new sequence, point 0 will default to being // stationary at 0, 0, and PinchArea will filter out that touchpoint because // it is outside its bounds. - pinchSequence.stationary(0).press(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.stationary(0).press(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); p1 -= QPoint(10,10); p2 += QPoint(10,10); - pinchSequence.move(0, p1, window).move(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); QCOMPARE(rect->scale(), 1.0); p1 -= QPoint(10, 0); p2 += QPoint(10, 0); - pinchSequence.move(0, p1, window).move(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); p1 -= QPoint(10, 0); p2 += QPoint(10, 0); - pinchSequence.move(0, p1, window).move(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); p1 -= QPoint(10, 0); p2 += QPoint(10, 0); - pinchSequence.move(0, p1, window).move(1, p2, window).commit(); - QQuickTouchUtils::flush(window); - pinchSequence.release(0, p1, window).release(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); + pinchSequence.release(0, p1, window.data()).release(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); QVERIFY(rect->scale() > 1.0); // PinchArea should steal the event after flicking started rect->setScale(1.0); flickable->setContentX(0.0); p = QPoint(100, 100); - pinchSequence.press(0, p, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.press(0, p, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); QCOMPARE(rect->position(), QPointF(200.0, 200.0)); p -= QPoint(10, 0); - pinchSequence.move(0, p, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); p -= QPoint(10, 0); - pinchSequence.move(0, p, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); QGuiApplication::processEvents(); p -= QPoint(10, 0); - pinchSequence.move(0, p, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); QCOMPARE(window->mouseGrabberItem(), flickable); // Add a second finger, this should lead to stealing p1 = QPoint(40, 100); p2 = QPoint(60, 100); - pinchSequence.stationary(0).press(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.stationary(0).press(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); QCOMPARE(rect->scale(), 1.0); p1 -= QPoint(5, 0); p2 += QPoint(5, 0); - pinchSequence.move(0, p1, window).move(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); p1 -= QPoint(5, 0); p2 += QPoint(5, 0); - pinchSequence.move(0, p1, window).move(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); p1 -= QPoint(5, 0); p2 += QPoint(5, 0); - pinchSequence.move(0, p1, window).move(1, p2, window).commit(); - QQuickTouchUtils::flush(window); - pinchSequence.release(0, p1, window).release(1, p2, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.move(0, p1, window.data()).move(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); + pinchSequence.release(0, p1, window.data()).release(1, p2, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); QVERIFY(rect->scale() > 1.0); - pinchSequence.release(0, p, window).commit(); - QQuickTouchUtils::flush(window); + pinchSequence.release(0, p, window.data()).commit(); + QQuickTouchUtils::flush(window.data()); } /* @@ -1176,13 +1142,11 @@ void tst_TouchMouse::mouseOnFlickableOnPinch() */ void tst_TouchMouse::tapOnDismissiveTopMouseAreaClicksBottomOne() { - QQuickView *window = createView(); - + QScopedPointer window(createView()); window->setSource(testFileUrl("twoMouseAreas.qml")); window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - window->requestActivate(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QQuickViewTestUtil::centerOnScreen(window.data()); + QVERIFY(QTest::qWaitForWindowActive(window.data())); QVERIFY(window->rootObject() != 0); QQuickMouseArea *bottomMouseArea = @@ -1194,23 +1158,21 @@ void tst_TouchMouse::tapOnDismissiveTopMouseAreaClicksBottomOne() // tap the front mouse area (see qml file) QPoint p1(20, 20); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); - QTest::touchEvent(window, device).release(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).release(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(bottomClickedSpy.count(), 1); QCOMPARE(bottomDoubleClickedSpy.count(), 0); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); - QTest::touchEvent(window, device).release(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).release(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(bottomClickedSpy.count(), 1); QCOMPARE(bottomDoubleClickedSpy.count(), 1); - - delete window; } /* @@ -1220,13 +1182,11 @@ void tst_TouchMouse::tapOnDismissiveTopMouseAreaClicksBottomOne() */ void tst_TouchMouse::touchGrabCausesMouseUngrab() { - QQuickView *window = createView(); - + QScopedPointer window(createView()); window->setSource(testFileUrl("twosiblingitems.qml")); window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - window->requestActivate(); - QVERIFY(QTest::qWaitForWindowActive(window)); + QQuickViewTestUtil::centerOnScreen(window.data()); + QVERIFY(QTest::qWaitForWindowActive(window.data())); QVERIFY(window->rootObject() != 0); EventItem *leftItem = window->rootObject()->findChild("leftItem"); @@ -1242,8 +1202,8 @@ void tst_TouchMouse::touchGrabCausesMouseUngrab() leftItem->setAcceptedMouseButtons(Qt::LeftButton); QPoint p1; p1 = QPoint(leftItem->width() / 2, leftItem->height() / 2); - QTest::touchEvent(window, device).press(0, p1, window); - QQuickTouchUtils::flush(window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); QCOMPARE(leftItem->eventList.size(), 2); QCOMPARE(leftItem->eventList.at(0).type, QEvent::TouchBegin); QCOMPARE(leftItem->eventList.at(1).type, QEvent::MouseButtonPress); @@ -1262,16 +1222,17 @@ void tst_TouchMouse::touchGrabCausesMouseUngrab() QCOMPARE(leftItem->eventList.size(), 1); QCOMPARE(leftItem->eventList.at(0).type, QEvent::UngrabMouse); QCOMPARE(window->mouseGrabberItem(), (QQuickItem*)0); - - delete window; } void tst_TouchMouse::touchPointDeliveryOrder() { // Touch points should be first delivered to the item under the primary finger QScopedPointer window(createView()); - window->setSource(testFileUrl("touchpointdeliveryorder.qml")); + window->show(); + QQuickViewTestUtil::centerOnScreen(window.data()); + QVERIFY(QTest::qWaitForWindowActive(window.data())); + /* The items are positioned from left to right: | background | @@ -1285,8 +1246,6 @@ void tst_TouchMouse::touchPointDeliveryOrder() QPoint pLeftMiddle = QPoint(200, 100); QPoint pRightMiddle = QPoint(350, 100); - window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window.data())); QVector events; EventItem *background = window->rootObject()->findChild("background"); @@ -1371,16 +1330,12 @@ void tst_TouchMouse::hoverEnabled() // device->setType(QTouchDevice::TouchScreen); // QWindowSystemInterface::registerTouchDevice(device); - // Ensure the cursor is away from the window - QCursor::setPos(0, 0); - - QQuickView *window = createView(); + QScopedPointer window(createView()); window->setSource(testFileUrl("hoverMouseAreas.qml")); - window->setPosition(10, 10); - + QQuickViewTestUtil::centerOnScreen(window.data()); + QQuickViewTestUtil::moveMouseAway(window.data()); window->show(); - window->requestActivate(); - QVERIFY(QTest::qWaitForWindowExposed(window)); + QVERIFY(QTest::qWaitForWindowActive(window.data())); QQuickItem *root = window->rootObject(); QVERIFY(root != 0); @@ -1403,14 +1358,14 @@ void tst_TouchMouse::hoverEnabled() QPoint p2(150, 250); // ------------------------- Mouse move to mouseArea1 - QTest::mouseMove(window, p1); + QTest::mouseMove(window.data(), p1); QVERIFY(enterSpy1.count() == 1); QVERIFY(mouseArea1->hovered()); QVERIFY(!mouseArea2->hovered()); // ------------------------- Touch click on mouseArea1 - QTest::touchEvent(window, device).press(0, p1, window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); QCOMPARE(enterSpy1.count(), 1); QCOMPARE(enterSpy2.count(), 0); @@ -1418,7 +1373,7 @@ void tst_TouchMouse::hoverEnabled() QVERIFY(mouseArea1->hovered()); QVERIFY(!mouseArea2->hovered()); - QTest::touchEvent(window, device).release(0, p1, window); + QTest::touchEvent(window.data(), device).release(0, p1, window.data()); QVERIFY(clickSpy1.count() == 1); QVERIFY(mouseArea1->hovered()); QVERIFY(!mouseArea2->hovered()); @@ -1427,7 +1382,7 @@ void tst_TouchMouse::hoverEnabled() if (QGuiApplication::platformName().compare(QLatin1String("xcb"), Qt::CaseInsensitive) == 0) QSKIP("hover can be momentarily inconsistent on X11, depending on timing of flushFrameSynchronousEvents with touch and mouse movements (QTBUG-55350)"); - QTest::touchEvent(window, device).press(0, p2, window); + QTest::touchEvent(window.data(), device).press(0, p2, window.data()); QVERIFY(mouseArea1->hovered()); QVERIFY(mouseArea2->hovered()); @@ -1435,7 +1390,7 @@ void tst_TouchMouse::hoverEnabled() QCOMPARE(enterSpy1.count(), 1); QCOMPARE(enterSpy2.count(), 1); - QTest::touchEvent(window, device).release(0, p2, window); + QTest::touchEvent(window.data(), device).release(0, p2, window.data()); QVERIFY(clickSpy2.count() == 1); QVERIFY(mouseArea1->hovered()); @@ -1444,7 +1399,7 @@ void tst_TouchMouse::hoverEnabled() QCOMPARE(exitSpy2.count(), 1); // ------------------------- Another touch click on mouseArea1 - QTest::touchEvent(window, device).press(0, p1, window); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); QCOMPARE(enterSpy1.count(), 1); QCOMPARE(enterSpy2.count(), 1); @@ -1452,7 +1407,7 @@ void tst_TouchMouse::hoverEnabled() QVERIFY(mouseArea1->hovered()); QVERIFY(!mouseArea2->hovered()); - QTest::touchEvent(window, device).release(0, p1, window); + QTest::touchEvent(window.data(), device).release(0, p1, window.data()); QCOMPARE(clickSpy1.count(), 2); QVERIFY(mouseArea1->hovered()); QVERIFY(!mouseArea1->pressed()); -- cgit v1.2.3 From 3057ec0447943fe022b66a2d19e13d94f9183a7c Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Thu, 5 Jan 2017 20:27:53 +0100 Subject: Port existing qmlInfo callers to qmlWarning Now that qmlInfo actually reports info messages, we want to change existing callers to use warning-level messages to preserve the original message level. This was done through: perl -p -i -e "s/qmlInfo\(/qmlWarning\(/" **/*.{cpp,h,qdoc} .. with a little care taken to only add the hunks that should be changed. Change-Id: I511cee11ce0a26ec1048cd2b84c7536b812a0d89 Reviewed-by: Simon Hausmann --- src/imports/statemachine/signaltransition.cpp | 2 +- src/imports/statemachine/state.cpp | 2 +- src/imports/statemachine/statemachine.cpp | 2 +- src/imports/statemachine/timeouttransition.cpp | 2 +- src/imports/xmllistmodel/qqmlxmllistmodel.cpp | 8 ++-- src/particles/qquickimageparticle.cpp | 8 ++-- src/particles/qquickmaskextruder.cpp | 2 +- src/qml/qml/qqmlabstractbinding.cpp | 2 +- src/qml/qml/qqmlboundsignal.cpp | 4 +- src/qml/qml/qqmlcomponent.cpp | 4 +- src/qml/qml/qqmlcustomparser.cpp | 2 +- src/qml/qml/qqmlloggingcategory.cpp | 4 +- src/qml/types/qqmlbind.cpp | 4 +- src/qml/types/qqmlconnections.cpp | 2 +- src/qml/types/qqmldelegatemodel.cpp | 60 +++++++++++++------------- src/qml/types/qqmllistmodel.cpp | 40 ++++++++--------- src/qml/types/qqmlobjectmodel.cpp | 6 +-- src/quick/items/context2d/qquickcanvasitem.cpp | 16 +++---- src/quick/items/qquickanchors.cpp | 34 +++++++-------- src/quick/items/qquickanimatedimage.cpp | 2 +- src/quick/items/qquickanimatedsprite.cpp | 2 +- src/quick/items/qquickborderimage.cpp | 2 +- src/quick/items/qquickdrag.cpp | 12 +++--- src/quick/items/qquickflipable.cpp | 4 +- src/quick/items/qquickimagebase.cpp | 2 +- src/quick/items/qquickitem.cpp | 8 ++-- src/quick/items/qquickitemanimation.cpp | 12 +++--- src/quick/items/qquickitemview.cpp | 4 +- src/quick/items/qquickloader.cpp | 2 +- src/quick/items/qquickpathview.cpp | 2 +- src/quick/items/qquickpositioners.cpp | 8 ++-- src/quick/items/qquickrepeater.cpp | 2 +- src/quick/items/qquickspriteengine.cpp | 10 ++--- src/quick/items/qquickspritesequence.cpp | 2 +- src/quick/items/qquickstateoperations.cpp | 8 ++-- src/quick/items/qquicktext.cpp | 2 +- src/quick/items/qquicktextdocument.cpp | 2 +- src/quick/items/qquicktextedit.cpp | 2 +- src/quick/items/qquicktextinput.cpp | 2 +- src/quick/items/qquicktextutil.cpp | 4 +- src/quick/util/qquickanimation.cpp | 18 ++++---- src/quick/util/qquickanimationcontroller.cpp | 2 +- src/quick/util/qquickbehavior.cpp | 2 +- src/quick/util/qquickfontloader.cpp | 2 +- src/quick/util/qquickpropertychanges.cpp | 4 +- src/quick/util/qquickstatechangescript.cpp | 2 +- src/quick/util/qquickstategroup.cpp | 2 +- 47 files changed, 165 insertions(+), 165 deletions(-) diff --git a/src/imports/statemachine/signaltransition.cpp b/src/imports/statemachine/signaltransition.cpp index 2e6381fc08..44fbf69431 100644 --- a/src/imports/statemachine/signaltransition.cpp +++ b/src/imports/statemachine/signaltransition.cpp @@ -127,7 +127,7 @@ void SignalTransition::setSignal(const QJSValue &signal) Q_ASSERT(sender); signalMethod = sender->metaObject()->method(signalObject->signalIndex()); } else { - qmlInfo(this) << tr("Specified signal does not exist."); + qmlWarning(this) << tr("Specified signal does not exist."); return; } diff --git a/src/imports/statemachine/state.cpp b/src/imports/statemachine/state.cpp index 09d246cc1e..f1294b0de0 100644 --- a/src/imports/statemachine/state.cpp +++ b/src/imports/statemachine/state.cpp @@ -54,7 +54,7 @@ void State::componentComplete() static bool once = false; if (!once) { once = true; - qmlInfo(this) << "No top level StateMachine found. Nothing will run without a StateMachine."; + qmlWarning(this) << "No top level StateMachine found. Nothing will run without a StateMachine."; } } } diff --git a/src/imports/statemachine/statemachine.cpp b/src/imports/statemachine/statemachine.cpp index 76de01fe94..a9ea5f7a95 100644 --- a/src/imports/statemachine/statemachine.cpp +++ b/src/imports/statemachine/statemachine.cpp @@ -69,7 +69,7 @@ void StateMachine::setRunning(bool running) void StateMachine::componentComplete() { if (QStateMachine::initialState() == NULL && childMode() == QState::ExclusiveStates) - qmlInfo(this) << "No initial state set for StateMachine"; + qmlWarning(this) << "No initial state set for StateMachine"; // Everything is proper setup, now start the state-machine if we got // asked to do so. diff --git a/src/imports/statemachine/timeouttransition.cpp b/src/imports/statemachine/timeouttransition.cpp index 4bb1df3c28..0d208b919b 100644 --- a/src/imports/statemachine/timeouttransition.cpp +++ b/src/imports/statemachine/timeouttransition.cpp @@ -72,7 +72,7 @@ void TimeoutTransition::componentComplete() { QState *state = qobject_cast(parent()); if (!state) { - qmlInfo(this) << "Parent needs to be a State"; + qmlWarning(this) << "Parent needs to be a State"; return; } diff --git a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp index 4306f477e9..61c8665a14 100644 --- a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp +++ b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp @@ -596,7 +596,7 @@ void QQuickXmlListModelPrivate::append_role(QQmlListPropertyd_func()->roleObjects.count(); _this->d_func()->roleObjects.append(role); if (_this->d_func()->roleNames.contains(role->name())) { - qmlInfo(role) << QQuickXmlListModel::tr("\"%1\" duplicates a previous role name and will be disabled.").arg(role->name()); + qmlWarning(role) << QQuickXmlListModel::tr("\"%1\" duplicates a previous role name and will be disabled.").arg(role->name()); return; } _this->d_func()->roles.insert(i, _this->d_func()->highestRole); @@ -847,7 +847,7 @@ void QQuickXmlListModel::setQuery(const QString &query) { Q_D(QQuickXmlListModel); if (!query.startsWith(QLatin1Char('/'))) { - qmlInfo(this) << QCoreApplication::translate("QQuickXmlRoleList", "An XmlListModel query must start with '/' or \"//\""); + qmlWarning(this) << QCoreApplication::translate("QQuickXmlRoleList", "An XmlListModel query must start with '/' or \"//\""); return; } @@ -1136,11 +1136,11 @@ void QQuickXmlListModel::queryError(void* object, const QString& error) Q_D(QQuickXmlListModel); for (int i=0; iroleObjects.count(); i++) { if (d->roleObjects.at(i) == static_cast(object)) { - qmlInfo(d->roleObjects.at(i)) << QQuickXmlListModel::tr("invalid query: \"%1\"").arg(error); + qmlWarning(d->roleObjects.at(i)) << QQuickXmlListModel::tr("invalid query: \"%1\"").arg(error); return; } } - qmlInfo(this) << QQuickXmlListModel::tr("invalid query: \"%1\"").arg(error); + qmlWarning(this) << QQuickXmlListModel::tr("invalid query: \"%1\"").arg(error); } void QQuickXmlListModel::queryCompleted(const QQuickXmlQueryResult &result) diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp index 60cbf6175d..e82f17becd 100644 --- a/src/particles/qquickimageparticle.cpp +++ b/src/particles/qquickimageparticle.cpp @@ -1347,21 +1347,21 @@ void QQuickImageParticle::finishBuildParticleNodes(QSGNode** node) if (m_colorTable->pix.isReady()) colortable = m_colorTable->pix.image(); else - qmlInfo(this) << "Error loading color table: " << m_colorTable->pix.error(); + qmlWarning(this) << "Error loading color table: " << m_colorTable->pix.error(); } if (m_sizeTable) { if (m_sizeTable->pix.isReady()) sizetable = m_sizeTable->pix.image(); else - qmlInfo(this) << "Error loading size table: " << m_sizeTable->pix.error(); + qmlWarning(this) << "Error loading size table: " << m_sizeTable->pix.error(); } if (m_opacityTable) { if (m_opacityTable->pix.isReady()) opacitytable = m_opacityTable->pix.image(); else - qmlInfo(this) << "Error loading opacity table: " << m_opacityTable->pix.error(); + qmlWarning(this) << "Error loading opacity table: " << m_opacityTable->pix.error(); } if (colortable.isNull()){//###Goes through image just for this @@ -1383,7 +1383,7 @@ void QQuickImageParticle::finishBuildParticleNodes(QSGNode** node) if (!imageLoaded) { if (!m_image || !m_image->pix.isReady()) { if (m_image) - qmlInfo(this) << m_image->pix.error(); + qmlWarning(this) << m_image->pix.error(); delete m_material; return; } diff --git a/src/particles/qquickmaskextruder.cpp b/src/particles/qquickmaskextruder.cpp index 66d5808c33..7564fa6739 100644 --- a/src/particles/qquickmaskextruder.cpp +++ b/src/particles/qquickmaskextruder.cpp @@ -94,7 +94,7 @@ void QQuickMaskExtruder::startMaskLoading() void QQuickMaskExtruder::finishMaskLoading() { if (m_pix.isError()) - qmlInfo(this) << m_pix.error(); + qmlWarning(this) << m_pix.error(); } QPointF QQuickMaskExtruder::extrude(const QRectF &r) diff --git a/src/qml/qml/qqmlabstractbinding.cpp b/src/qml/qml/qqmlabstractbinding.cpp index 39d609454f..b1c320afd4 100644 --- a/src/qml/qml/qqmlabstractbinding.cpp +++ b/src/qml/qml/qqmlabstractbinding.cpp @@ -191,7 +191,7 @@ void QQmlAbstractBinding::removeFromObject() void QQmlAbstractBinding::printBindingLoopError(QQmlProperty &prop) { - qmlInfo(prop.object()) << QString(QLatin1String("Binding loop detected for property \"%1\"")).arg(prop.name()); + qmlWarning(prop.object()) << QString(QLatin1String("Binding loop detected for property \"%1\"")).arg(prop.name()); } QString QQmlAbstractBinding::expression() const diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index 254d5e1907..d5b2067094 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -91,7 +91,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, function += QQmlPropertyCache::signalParameterStringForJS(v4, signal.parameterNames(), &error); if (!error.isEmpty()) { - qmlInfo(scopeObject()) << error; + qmlWarning(scopeObject()) << error; return; } } else @@ -129,7 +129,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QString error; QQmlPropertyCache::signalParameterStringForJS(engine, signalParameters, &error); if (!error.isEmpty()) { - qmlInfo(scopeObject()) << error; + qmlWarning(scopeObject()) << error; return; } runtimeFunction->updateInternalClass(engine, signalParameters); diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 6ebcd142fb..936313768a 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1244,7 +1244,7 @@ void QQmlComponent::createObject(QQmlV4Function *args) if (args->length() >= 2) { QV4::ScopedValue v(scope, (*args)[1]); if (!v->as() || v->as()) { - qmlInfo(this) << tr("createObject: value is not an object"); + qmlWarning(this) << tr("createObject: value is not an object"); args->setReturnValue(QV4::Encode::null()); return; } @@ -1361,7 +1361,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args) QV4::ScopedValue v(scope, (*args)[1]); if (v->isNull()) { } else if (!v->as() || v->as()) { - qmlInfo(this) << tr("createObject: value is not an object"); + qmlWarning(this) << tr("createObject: value is not an object"); args->setReturnValue(QV4::Encode::null()); return; } else { diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp index 85c91a592a..0b0bbef795 100644 --- a/src/qml/qml/qqmlcustomparser.cpp +++ b/src/qml/qml/qqmlcustomparser.cpp @@ -83,7 +83,7 @@ QT_BEGIN_NAMESPACE by \a data, which is a block of data previously returned by a call to compile(). - Errors should be reported using qmlInfo(object). + Errors should be reported using qmlWarning(object). The \a object will be an instance of the TypeClass specified by QML_REGISTER_CUSTOM_TYPE. */ diff --git a/src/qml/qml/qqmlloggingcategory.cpp b/src/qml/qml/qqmlloggingcategory.cpp index 70e59db07b..764b874131 100644 --- a/src/qml/qml/qqmlloggingcategory.cpp +++ b/src/qml/qml/qqmlloggingcategory.cpp @@ -112,13 +112,13 @@ void QQmlLoggingCategory::componentComplete() { m_initialized = true; if (m_name.isNull()) - qmlInfo(this) << QLatin1String("Declaring the name of the LoggingCategory is mandatory and cannot be changed later !"); + qmlWarning(this) << QLatin1String("Declaring the name of the LoggingCategory is mandatory and cannot be changed later !"); } void QQmlLoggingCategory::setName(const QString &name) { if (m_initialized) { - qmlInfo(this) << QLatin1String("The name of a LoggingCategory cannot be changed after the Item is created"); + qmlWarning(this) << QLatin1String("The name of a LoggingCategory cannot be changed after the Item is created"); return; } diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp index a545fe57ca..2ded9c13c8 100644 --- a/src/qml/types/qqmlbind.cpp +++ b/src/qml/types/qqmlbind.cpp @@ -82,12 +82,12 @@ void QQmlBindPrivate::validate(QObject *binding) const return; if (!prop.isValid()) { - qmlInfo(binding) << "Property '" << propName << "' does not exist on " << QQmlMetaType::prettyTypeName(obj) << "."; + qmlWarning(binding) << "Property '" << propName << "' does not exist on " << QQmlMetaType::prettyTypeName(obj) << "."; return; } if (!prop.isWritable()) { - qmlInfo(binding) << "Property '" << propName << "' on " << QQmlMetaType::prettyTypeName(obj) << " is read-only."; + qmlWarning(binding) << "Property '" << propName << "' on " << QQmlMetaType::prettyTypeName(obj) << " is read-only."; return; } } diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp index 2aed4d9972..864ecf54dd 100644 --- a/src/qml/types/qqmlconnections.cpp +++ b/src/qml/types/qqmlconnections.cpp @@ -295,7 +295,7 @@ void QQmlConnections::connectSignals() d->boundsignals += signal; } else { if (!d->ignoreUnknownSignals) - qmlInfo(this) << tr("Cannot assign to non-existent property \"%1\"").arg(propName); + qmlWarning(this) << tr("Cannot assign to non-existent property \"%1\"").arg(propName); } } } diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index be10b270ae..c635ccf79c 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -310,7 +310,7 @@ void QQmlDelegateModel::componentComplete() --d->m_groupCount; --i; } else if (name.at(0).isUpper()) { - qmlInfo(d->m_groups[i]) << QQmlDelegateModelGroup::tr("Group names must start with a lower case letter"); + qmlWarning(d->m_groups[i]) << QQmlDelegateModelGroup::tr("Group names must start with a lower case letter"); d->m_groups[i] = d->m_groups[d->m_groupCount - 1]; --d->m_groupCount; --i; @@ -404,7 +404,7 @@ void QQmlDelegateModel::setDelegate(QQmlComponent *delegate) { Q_D(QQmlDelegateModel); if (d->m_transaction) { - qmlInfo(this) << tr("The delegate of a DelegateModel cannot be changed within onUpdated."); + qmlWarning(this) << tr("The delegate of a DelegateModel cannot be changed within onUpdated."); return; } bool wasValid = d->m_delegate != 0; @@ -610,7 +610,7 @@ void QQmlDelegateModelPrivate::group_append( if (d->m_complete) return; if (d->m_groupCount == Compositor::MaximumGroupCount) { - qmlInfo(d->q_func()) << QQmlDelegateModel::tr("The maximum number of supported DelegateModelGroups is 8"); + qmlWarning(d->q_func()) << QQmlDelegateModel::tr("The maximum number of supported DelegateModelGroups is 8"); return; } d->m_groups[d->m_groupCount] = group; @@ -719,7 +719,7 @@ void QQmlDelegateModel::setFilterGroup(const QString &group) Q_D(QQmlDelegateModel); if (d->m_transaction) { - qmlInfo(this) << tr("The group of a DelegateModel cannot be changed within onChanged"); + qmlWarning(this) << tr("The group of a DelegateModel cannot be changed within onChanged"); return; } @@ -889,7 +889,7 @@ void QQmlDelegateModelPrivate::incubatorStatusChanged(QQDMIncubationTask *incuba emitCreatedItem(incubationTask, cacheItem->object); cacheItem->releaseObject(); } else if (status == QQmlIncubator::Error) { - qmlInfo(q, m_delegate->errors()) << "Error creating delegate"; + qmlWarning(q, m_delegate->errors()) << "Error creating delegate"; } if (!cacheItem->isObjectReferenced()) { @@ -2459,7 +2459,7 @@ QQmlV4Handle QQmlDelegateModelGroup::get(int index) if (!model->m_context || !model->m_context->isValid()) { return QQmlV4Handle(QV4::Encode::undefined()); } else if (index < 0 || index >= model->m_compositor.count(d->group)) { - qmlInfo(this) << tr("get: index out of range"); + qmlWarning(this) << tr("get: index out of range"); return QQmlV4Handle(QV4::Encode::undefined()); } @@ -2552,7 +2552,7 @@ void QQmlDelegateModelGroup::insert(QQmlV4Function *args) QV4::ScopedValue v(scope, (*args)[i]); if (d->parseIndex(v, &index, &group)) { if (index < 0 || index > model->m_compositor.count(group)) { - qmlInfo(this) << tr("insert: index out of range"); + qmlWarning(this) << tr("insert: index out of range"); return; } if (++i == args->length()) @@ -2637,7 +2637,7 @@ void QQmlDelegateModelGroup::create(QQmlV4Function *args) } } if (index < 0 || index >= model->m_compositor.count(group)) { - qmlInfo(this) << tr("create: index out of range"); + qmlWarning(this) << tr("create: index out of range"); return; } @@ -2690,22 +2690,22 @@ void QQmlDelegateModelGroup::resolve(QQmlV4Function *args) QV4::ScopedValue v(scope, (*args)[0]); if (d->parseIndex(v, &from, &fromGroup)) { if (from < 0 || from >= model->m_compositor.count(fromGroup)) { - qmlInfo(this) << tr("resolve: from index out of range"); + qmlWarning(this) << tr("resolve: from index out of range"); return; } } else { - qmlInfo(this) << tr("resolve: from index invalid"); + qmlWarning(this) << tr("resolve: from index invalid"); return; } v = (*args)[1]; if (d->parseIndex(v, &to, &toGroup)) { if (to < 0 || to >= model->m_compositor.count(toGroup)) { - qmlInfo(this) << tr("resolve: to index out of range"); + qmlWarning(this) << tr("resolve: to index out of range"); return; } } else { - qmlInfo(this) << tr("resolve: to index invalid"); + qmlWarning(this) << tr("resolve: to index invalid"); return; } @@ -2713,11 +2713,11 @@ void QQmlDelegateModelGroup::resolve(QQmlV4Function *args) Compositor::iterator toIt = model->m_compositor.find(toGroup, to); if (!fromIt->isUnresolved()) { - qmlInfo(this) << tr("resolve: from is not an unresolved item"); + qmlWarning(this) << tr("resolve: from is not an unresolved item"); return; } if (!toIt->list) { - qmlInfo(this) << tr("resolve: to is not a model item"); + qmlWarning(this) << tr("resolve: to is not a model item"); return; } @@ -2787,7 +2787,7 @@ void QQmlDelegateModelGroup::remove(QQmlV4Function *args) QV4::Scope scope(args->v4engine()); QV4::ScopedValue v(scope, (*args)[0]); if (!d->parseIndex(v, &index, &group)) { - qmlInfo(this) << tr("remove: invalid index"); + qmlWarning(this) << tr("remove: invalid index"); return; } @@ -2799,11 +2799,11 @@ void QQmlDelegateModelGroup::remove(QQmlV4Function *args) QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model); if (index < 0 || index >= model->m_compositor.count(group)) { - qmlInfo(this) << tr("remove: index out of range"); + qmlWarning(this) << tr("remove: index out of range"); } else if (count != 0) { Compositor::iterator it = model->m_compositor.find(group, index); if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) { - qmlInfo(this) << tr("remove: invalid count"); + qmlWarning(this) << tr("remove: invalid count"); } else { model->removeGroups(it, count, d->group, 1 << d->group); } @@ -2858,11 +2858,11 @@ void QQmlDelegateModelGroup::addGroups(QQmlV4Function *args) QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model); if (index < 0 || index >= model->m_compositor.count(group)) { - qmlInfo(this) << tr("addGroups: index out of range"); + qmlWarning(this) << tr("addGroups: index out of range"); } else if (count != 0) { Compositor::iterator it = model->m_compositor.find(group, index); if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) { - qmlInfo(this) << tr("addGroups: invalid count"); + qmlWarning(this) << tr("addGroups: invalid count"); } else { model->addGroups(it, count, d->group, groups); } @@ -2888,11 +2888,11 @@ void QQmlDelegateModelGroup::removeGroups(QQmlV4Function *args) QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model); if (index < 0 || index >= model->m_compositor.count(group)) { - qmlInfo(this) << tr("removeGroups: index out of range"); + qmlWarning(this) << tr("removeGroups: index out of range"); } else if (count != 0) { Compositor::iterator it = model->m_compositor.find(group, index); if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) { - qmlInfo(this) << tr("removeGroups: invalid count"); + qmlWarning(this) << tr("removeGroups: invalid count"); } else { model->removeGroups(it, count, d->group, groups); } @@ -2918,11 +2918,11 @@ void QQmlDelegateModelGroup::setGroups(QQmlV4Function *args) QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model); if (index < 0 || index >= model->m_compositor.count(group)) { - qmlInfo(this) << tr("setGroups: index out of range"); + qmlWarning(this) << tr("setGroups: index out of range"); } else if (count != 0) { Compositor::iterator it = model->m_compositor.find(group, index); if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) { - qmlInfo(this) << tr("setGroups: invalid count"); + qmlWarning(this) << tr("setGroups: invalid count"); } else { model->setGroups(it, count, d->group, groups); } @@ -2957,13 +2957,13 @@ void QQmlDelegateModelGroup::move(QQmlV4Function *args) QV4::Scope scope(args->v4engine()); QV4::ScopedValue v(scope, (*args)[0]); if (!d->parseIndex(v, &from, &fromGroup)) { - qmlInfo(this) << tr("move: invalid from index"); + qmlWarning(this) << tr("move: invalid from index"); return; } v = (*args)[1]; if (!d->parseIndex(v, &to, &toGroup)) { - qmlInfo(this) << tr("move: invalid to index"); + qmlWarning(this) << tr("move: invalid to index"); return; } @@ -2976,11 +2976,11 @@ void QQmlDelegateModelGroup::move(QQmlV4Function *args) QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model); if (count < 0) { - qmlInfo(this) << tr("move: invalid count"); + qmlWarning(this) << tr("move: invalid count"); } else if (from < 0 || from + count > model->m_compositor.count(fromGroup)) { - qmlInfo(this) << tr("move: from index out of range"); + qmlWarning(this) << tr("move: from index out of range"); } else if (!model->m_compositor.verifyMoveTo(fromGroup, from, toGroup, to, count, d->group)) { - qmlInfo(this) << tr("move: to index out of range"); + qmlWarning(this) << tr("move: to index out of range"); } else if (count > 0) { QVector removes; QVector inserts; @@ -3038,7 +3038,7 @@ QString QQmlPartsModel::filterGroup() const void QQmlPartsModel::setFilterGroup(const QString &group) { if (QQmlDelegateModelPrivate::get(m_model)->m_transaction) { - qmlInfo(this) << tr("The group of a DelegateModel cannot be changed within onChanged"); + qmlWarning(this) << tr("The group of a DelegateModel cannot be changed within onChanged"); return; } @@ -3151,7 +3151,7 @@ QObject *QQmlPartsModel::object(int index, bool asynchronous) model->release(object); if (!model->m_delegateValidated) { if (object) - qmlInfo(model->m_delegate) << tr("Delegate component must be Package type."); + qmlWarning(model->m_delegate) << tr("Delegate component must be Package type."); model->m_delegateValidated = true; } diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index 1a2e4c7f6f..5e06455b26 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -99,7 +99,7 @@ const ListLayout::Role &ListLayout::getRoleOrCreate(const QString &key, Role::Da if (node) { const Role &r = *node->value; if (type != r.type) - qmlInfo(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type)); + qmlWarning(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type)); return r; } @@ -112,7 +112,7 @@ const ListLayout::Role &ListLayout::getRoleOrCreate(QV4::String *key, Role::Data if (node) { const Role &r = *node->value; if (type != r.type) - qmlInfo(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type)); + qmlWarning(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type)); return r; } @@ -226,7 +226,7 @@ const ListLayout::Role *ListLayout::getRoleOrCreate(const QString &key, const QV } if (type == Role::Invalid) { - qmlInfo(0) << "Can't create role for unsupported data type"; + qmlWarning(0) << "Can't create role for unsupported data type"; return 0; } @@ -1201,7 +1201,7 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d } roleIndex = setListProperty(role, subModel); } else { - qmlInfo(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(role.name).arg(roleTypeName(role.type)).arg(roleTypeName(ListLayout::Role::List)); + qmlWarning(0) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(role.name).arg(roleTypeName(role.type)).arg(roleTypeName(ListLayout::Role::List)); } } else if (d.isBoolean()) { roleIndex = setBoolProperty(role, d.booleanValue()); @@ -1984,18 +1984,18 @@ void QQmlListModel::setDynamicRoles(bool enableDynamicRoles) if (m_mainThread && m_agent == 0) { if (enableDynamicRoles) { if (m_layout->roleCount()) - qmlInfo(this) << tr("unable to enable dynamic roles as this model is not empty!"); + qmlWarning(this) << tr("unable to enable dynamic roles as this model is not empty!"); else m_dynamicRoles = true; } else { if (m_roles.count()) { - qmlInfo(this) << tr("unable to enable static roles as this model is not empty!"); + qmlWarning(this) << tr("unable to enable static roles as this model is not empty!"); } else { m_dynamicRoles = false; } } } else { - qmlInfo(this) << tr("dynamic role setting must be made from the main thread, before any worker scripts are created"); + qmlWarning(this) << tr("dynamic role setting must be made from the main thread, before any worker scripts are created"); } } @@ -2048,7 +2048,7 @@ void QQmlListModel::remove(QQmlV4Function *args) int removeCount = (argLength == 2 ? QV4::ScopedValue(scope, (*args)[1])->toInt32() : 1); if (index < 0 || index+removeCount > count() || removeCount <= 0) { - qmlInfo(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+removeCount).arg(count()); + qmlWarning(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+removeCount).arg(count()); return; } @@ -2064,7 +2064,7 @@ void QQmlListModel::remove(QQmlV4Function *args) emitItemsRemoved(index, removeCount); } else { - qmlInfo(this) << tr("remove: incorrect number of arguments"); + qmlWarning(this) << tr("remove: incorrect number of arguments"); } } @@ -2092,7 +2092,7 @@ void QQmlListModel::insert(QQmlV4Function *args) int index = arg0->toInt32(); if (index < 0 || index > count()) { - qmlInfo(this) << tr("insert: index %1 out of range").arg(index); + qmlWarning(this) << tr("insert: index %1 out of range").arg(index); return; } @@ -2124,10 +2124,10 @@ void QQmlListModel::insert(QQmlV4Function *args) emitItemsInserted(index, 1); } else { - qmlInfo(this) << tr("insert: value is not an object"); + qmlWarning(this) << tr("insert: value is not an object"); } } else { - qmlInfo(this) << tr("insert: value is not an object"); + qmlWarning(this) << tr("insert: value is not an object"); } } @@ -2150,7 +2150,7 @@ void QQmlListModel::move(int from, int to, int n) if (n==0 || from==to) return; if (!canMove(from, to, n)) { - qmlInfo(this) << tr("move: out of range"); + qmlWarning(this) << tr("move: out of range"); return; } @@ -2239,10 +2239,10 @@ void QQmlListModel::append(QQmlV4Function *args) emitItemsInserted(index, 1); } else { - qmlInfo(this) << tr("append: value is not an object"); + qmlWarning(this) << tr("append: value is not an object"); } } else { - qmlInfo(this) << tr("append: value is not an object"); + qmlWarning(this) << tr("append: value is not an object"); } } @@ -2321,11 +2321,11 @@ void QQmlListModel::set(int index, const QQmlV4Handle &handle) QV4::ScopedObject object(scope, handle); if (!object) { - qmlInfo(this) << tr("set: value is not an object"); + qmlWarning(this) << tr("set: value is not an object"); return; } if (index > count() || index < 0) { - qmlInfo(this) << tr("set: index %1 out of range").arg(index); + qmlWarning(this) << tr("set: index %1 out of range").arg(index); return; } @@ -2371,7 +2371,7 @@ void QQmlListModel::set(int index, const QQmlV4Handle &handle) void QQmlListModel::setProperty(int index, const QString& property, const QVariant& value) { if (count() == 0 || index >= count() || index < 0) { - qmlInfo(this) << tr("set: index %1 out of range").arg(index); + qmlWarning(this) << tr("set: index %1 out of range").arg(index); return; } @@ -2401,7 +2401,7 @@ void QQmlListModel::sync() // This is just a dummy method to make it look like sync() exists in // ListModel (and not just QQmlListModelWorkerAgent) and to let // us document sync(). - qmlInfo(this) << "List sync() can only be called from a WorkerScript"; + qmlWarning(this) << "List sync() can only be called from a WorkerScript"; } bool QQmlListModelParser::verifyProperty(const QV4::CompiledData::Unit *qmlUnit, const QV4::CompiledData::Binding *binding) @@ -2543,7 +2543,7 @@ void QQmlListModelParser::applyBindings(QObject *obj, QV4::CompiledData::Compila } if (setRoles == false) - qmlInfo(obj) << "All ListElement declarations are empty, no roles can be created unless dynamicRoles is set."; + qmlWarning(obj) << "All ListElement declarations are empty, no roles can be created unless dynamicRoles is set."; } bool QQmlListModelParser::definesEmptyList(const QString &s) diff --git a/src/qml/types/qqmlobjectmodel.cpp b/src/qml/types/qqmlobjectmodel.cpp index 695043b592..21205f4490 100644 --- a/src/qml/types/qqmlobjectmodel.cpp +++ b/src/qml/types/qqmlobjectmodel.cpp @@ -373,7 +373,7 @@ void QQmlObjectModel::insert(int index, QObject *object) { Q_D(QQmlObjectModel); if (index < 0 || index > count()) { - qmlInfo(this) << tr("insert: index %1 out of range").arg(index); + qmlWarning(this) << tr("insert: index %1 out of range").arg(index); return; } d->insert(index, object); @@ -400,7 +400,7 @@ void QQmlObjectModel::move(int from, int to, int n) if (n <= 0 || from == to) return; if (from < 0 || to < 0 || from + n > count() || to + n > count()) { - qmlInfo(this) << tr("move: out of range"); + qmlWarning(this) << tr("move: out of range"); return; } d->move(from, to, n); @@ -418,7 +418,7 @@ void QQmlObjectModel::remove(int index, int n) { Q_D(QQmlObjectModel); if (index < 0 || n <= 0 || index + n > count()) { - qmlInfo(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+n).arg(count()); + qmlWarning(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+n).arg(count()); return; } d->remove(index, n); diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index 78db92ba8a..d376816ef9 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -354,7 +354,7 @@ void QQuickCanvasItem::setContextType(const QString &contextType) return; if (d->context) { - qmlInfo(this) << "Canvas already initialized with a different context type"; + qmlWarning(this) << "Canvas already initialized with a different context type"; return; } @@ -517,7 +517,7 @@ void QQuickCanvasItem::setRenderTarget(QQuickCanvasItem::RenderTarget target) Q_D(QQuickCanvasItem); if (d->renderTarget != target) { if (d->context) { - qmlInfo(this) << "Canvas:renderTarget not changeble once context is active."; + qmlWarning(this) << "Canvas:renderTarget not changeble once context is active."; return; } @@ -561,7 +561,7 @@ void QQuickCanvasItem::setRenderStrategy(QQuickCanvasItem::RenderStrategy strate Q_D(QQuickCanvasItem); if (d->renderStrategy != strategy) { if (d->context) { - qmlInfo(this) << "Canvas:renderStrategy not changeable once context is active."; + qmlWarning(this) << "Canvas:renderStrategy not changeable once context is active."; return; } d->renderStrategy = strategy; @@ -840,13 +840,13 @@ void QQuickCanvasItem::getContext(QQmlV4Function *args) QV4::Scope scope(args->v4engine()); QV4::ScopedString str(scope, (*args)[0]); if (!str) { - qmlInfo(this) << "getContext should be called with a string naming the required context type"; + qmlWarning(this) << "getContext should be called with a string naming the required context type"; args->setReturnValue(QV4::Encode::null()); return; } if (!d->available) { - qmlInfo(this) << "Unable to use getContext() at this time, please wait for available: true"; + qmlWarning(this) << "Unable to use getContext() at this time, please wait for available: true"; args->setReturnValue(QV4::Encode::null()); return; } @@ -859,7 +859,7 @@ void QQuickCanvasItem::getContext(QQmlV4Function *args) return; } - qmlInfo(this) << "Canvas already initialized with a different context type"; + qmlWarning(this) << "Canvas already initialized with a different context type"; args->setReturnValue(QV4::Encode::null()); return; } @@ -882,7 +882,7 @@ void QQuickCanvasItem::requestAnimationFrame(QQmlV4Function *args) QV4::Scope scope(args->v4engine()); QV4::ScopedFunctionObject f(scope, (*args)[0]); if (!f) { - qmlInfo(this) << "requestAnimationFrame should be called with an animation callback function"; + qmlWarning(this) << "requestAnimationFrame should be called with an animation callback function"; args->setReturnValue(QV4::Encode::null()); return; } @@ -910,7 +910,7 @@ void QQuickCanvasItem::cancelRequestAnimationFrame(QQmlV4Function *args) QV4::Scope scope(args->v4engine()); QV4::ScopedValue v(scope, (*args)[0]); if (!v->isInteger()) { - qmlInfo(this) << "cancelRequestAnimationFrame should be called with an animation callback id"; + qmlWarning(this) << "cancelRequestAnimationFrame should be called with an animation callback id"; args->setReturnValue(QV4::Encode::null()); return; } diff --git a/src/quick/items/qquickanchors.cpp b/src/quick/items/qquickanchors.cpp index 4162314cd3..c0bec7d716 100644 --- a/src/quick/items/qquickanchors.cpp +++ b/src/quick/items/qquickanchors.cpp @@ -214,7 +214,7 @@ void QQuickAnchorsPrivate::fillChanged() --updatingFill; } else { // ### Make this certain :) - qmlInfo(item) << QQuickAnchors::tr("Possible anchor loop detected on fill."); + qmlWarning(item) << QQuickAnchors::tr("Possible anchor loop detected on fill."); } } @@ -243,7 +243,7 @@ void QQuickAnchorsPrivate::centerInChanged() --updatingCenterIn; } else { // ### Make this certain :) - qmlInfo(item) << QQuickAnchors::tr("Possible anchor loop detected on centerIn."); + qmlWarning(item) << QQuickAnchors::tr("Possible anchor loop detected on centerIn."); } } @@ -529,7 +529,7 @@ void QQuickAnchors::setFill(QQuickItem *f) return; } if (f != readParentItem(d->item) && readParentItem(f) != readParentItem(d->item)){ - qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling."); + qmlWarning(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling."); return; } QQuickItem *oldFill = d->fill; @@ -565,7 +565,7 @@ void QQuickAnchors::setCenterIn(QQuickItem* c) return; } if (c != readParentItem(d->item) && readParentItem(c) != readParentItem(d->item)){ - qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling."); + qmlWarning(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling."); return; } QQuickItem *oldCI = d->centerIn; @@ -619,7 +619,7 @@ void QQuickAnchorsPrivate::updateVerticalAnchors() if (Q_UNLIKELY(updatingVerticalAnchor > 1)) { // ### Make this certain :) - qmlInfo(item) << QQuickAnchors::tr("Possible anchor loop detected on vertical anchor."); + qmlWarning(item) << QQuickAnchors::tr("Possible anchor loop detected on vertical anchor."); return; } @@ -794,7 +794,7 @@ void QQuickAnchorsPrivate::updateHorizontalAnchors() --updatingHorizontalAnchor; } else { // ### Make this certain :) - qmlInfo(item) << QQuickAnchors::tr("Possible anchor loop detected on horizontal anchor."); + qmlWarning(item) << QQuickAnchors::tr("Possible anchor loop detected on horizontal anchor."); } } @@ -1329,7 +1329,7 @@ bool QQuickAnchorsPrivate::checkHValid() const if (usedAnchors & QQuickAnchors::LeftAnchor && usedAnchors & QQuickAnchors::RightAnchor && usedAnchors & QQuickAnchors::HCenterAnchor) { - qmlInfo(item) << QQuickAnchors::tr("Cannot specify left, right, and horizontalCenter anchors at the same time."); + qmlWarning(item) << QQuickAnchors::tr("Cannot specify left, right, and horizontalCenter anchors at the same time."); return false; } @@ -1339,17 +1339,17 @@ bool QQuickAnchorsPrivate::checkHValid() const bool QQuickAnchorsPrivate::checkHAnchorValid(QQuickAnchorLine anchor) const { if (!anchor.item) { - qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to a null item."); + qmlWarning(item) << QQuickAnchors::tr("Cannot anchor to a null item."); return false; } else if (anchor.anchorLine & QQuickAnchors::Vertical_Mask) { - qmlInfo(item) << QQuickAnchors::tr("Cannot anchor a horizontal edge to a vertical edge."); + qmlWarning(item) << QQuickAnchors::tr("Cannot anchor a horizontal edge to a vertical edge."); return false; } else if (anchor.item != readParentItem(item) && readParentItem(anchor.item) != readParentItem(item)) { - qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling."); + qmlWarning(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling."); return false; } else if (anchor.item == item) { - qmlInfo(item) << QQuickAnchors::tr("Cannot anchor item to self."); + qmlWarning(item) << QQuickAnchors::tr("Cannot anchor item to self."); return false; } @@ -1361,13 +1361,13 @@ bool QQuickAnchorsPrivate::checkVValid() const if (usedAnchors & QQuickAnchors::TopAnchor && usedAnchors & QQuickAnchors::BottomAnchor && usedAnchors & QQuickAnchors::VCenterAnchor) { - qmlInfo(item) << QQuickAnchors::tr("Cannot specify top, bottom, and verticalCenter anchors at the same time."); + qmlWarning(item) << QQuickAnchors::tr("Cannot specify top, bottom, and verticalCenter anchors at the same time."); return false; } else if (usedAnchors & QQuickAnchors::BaselineAnchor && (usedAnchors & QQuickAnchors::TopAnchor || usedAnchors & QQuickAnchors::BottomAnchor || usedAnchors & QQuickAnchors::VCenterAnchor)) { - qmlInfo(item) << QQuickAnchors::tr("Baseline anchor cannot be used in conjunction with top, bottom, or verticalCenter anchors."); + qmlWarning(item) << QQuickAnchors::tr("Baseline anchor cannot be used in conjunction with top, bottom, or verticalCenter anchors."); return false; } @@ -1377,17 +1377,17 @@ bool QQuickAnchorsPrivate::checkVValid() const bool QQuickAnchorsPrivate::checkVAnchorValid(QQuickAnchorLine anchor) const { if (!anchor.item) { - qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to a null item."); + qmlWarning(item) << QQuickAnchors::tr("Cannot anchor to a null item."); return false; } else if (anchor.anchorLine & QQuickAnchors::Horizontal_Mask) { - qmlInfo(item) << QQuickAnchors::tr("Cannot anchor a vertical edge to a horizontal edge."); + qmlWarning(item) << QQuickAnchors::tr("Cannot anchor a vertical edge to a horizontal edge."); return false; } else if (anchor.item != readParentItem(item) && readParentItem(anchor.item) != readParentItem(item)) { - qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling."); + qmlWarning(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling."); return false; } else if (anchor.item == item){ - qmlInfo(item) << QQuickAnchors::tr("Cannot anchor item to self."); + qmlWarning(item) << QQuickAnchors::tr("Cannot anchor item to self."); return false; } diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp index 81c649dbd5..a1833081c8 100644 --- a/src/quick/items/qquickanimatedimage.cpp +++ b/src/quick/items/qquickanimatedimage.cpp @@ -371,7 +371,7 @@ void QQuickAnimatedImage::movieRequestFinished() #endif if (!d->_movie->isValid()) { - qmlInfo(this) << "Error Reading Animated Image File " << d->url.toString(); + qmlWarning(this) << "Error Reading Animated Image File " << d->url.toString(); delete d->_movie; d->_movie = 0; d->setImage(QImage()); diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp index 8aeef4ef4a..76c2146ddb 100644 --- a/src/quick/items/qquickanimatedsprite.cpp +++ b/src/quick/items/qquickanimatedsprite.cpp @@ -626,7 +626,7 @@ QSGSpriteNode* QQuickAnimatedSprite::initNode() Q_D(QQuickAnimatedSprite); if (!d->m_spriteEngine) { - qmlInfo(this) << "No sprite engine..."; + qmlWarning(this) << "No sprite engine..."; return nullptr; } else if (d->m_spriteEngine->status() == QQuickPixmap::Null) { d->m_spriteEngine->startAssemblingImage(); diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp index 67b99bfbc6..28d834f9e2 100644 --- a/src/quick/items/qquickborderimage.cpp +++ b/src/quick/items/qquickborderimage.cpp @@ -515,7 +515,7 @@ void QQuickBorderImage::requestFinished() QSize impsize = d->pix.implicitSize(); if (d->pix.isError()) { d->status = Error; - qmlInfo(this) << d->pix.error(); + qmlWarning(this) << d->pix.error(); if (d->progress != 0) { d->progress = 0; emit progressChanged(d->progress); diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp index 7a112e840a..e5969eed7f 100644 --- a/src/quick/items/qquickdrag.cpp +++ b/src/quick/items/qquickdrag.cpp @@ -307,7 +307,7 @@ void QQuickDragAttached::setActive(bool active) Q_D(QQuickDragAttached); if (d->active != active) { if (d->inEvent) - qmlInfo(this) << "active cannot be changed from within a drag event handler"; + qmlWarning(this) << "active cannot be changed from within a drag event handler"; else if (active) { if (d->dragType == QQuickDrag::Internal) { d->start(d->supportedActions); @@ -629,7 +629,7 @@ void QQuickDragAttached::start(QQmlV4Function *args) { Q_D(QQuickDragAttached); if (d->inEvent) { - qmlInfo(this) << "start() cannot be called from within a drag event handler"; + qmlWarning(this) << "start() cannot be called from within a drag event handler"; return; } @@ -675,7 +675,7 @@ int QQuickDragAttached::drop() Qt::DropAction acceptedAction = Qt::IgnoreAction; if (d->inEvent) { - qmlInfo(this) << "drop() cannot be called from within a drag event handler"; + qmlWarning(this) << "drop() cannot be called from within a drag event handler"; return acceptedAction; } @@ -722,7 +722,7 @@ void QQuickDragAttached::cancel() Q_D(QQuickDragAttached); if (d->inEvent) { - qmlInfo(this) << "cancel() cannot be called from within a drag event handler"; + qmlWarning(this) << "cancel() cannot be called from within a drag event handler"; return; } @@ -809,12 +809,12 @@ void QQuickDragAttached::startDrag(QQmlV4Function *args) Q_D(QQuickDragAttached); if (d->inEvent) { - qmlInfo(this) << "startDrag() cannot be called from within a drag event handler"; + qmlWarning(this) << "startDrag() cannot be called from within a drag event handler"; return; } if (!d->active) { - qmlInfo(this) << "startDrag() drag must be active"; + qmlWarning(this) << "startDrag() drag must be active"; return; } diff --git a/src/quick/items/qquickflipable.cpp b/src/quick/items/qquickflipable.cpp index 6a6b6c00a9..f452893528 100644 --- a/src/quick/items/qquickflipable.cpp +++ b/src/quick/items/qquickflipable.cpp @@ -153,7 +153,7 @@ void QQuickFlipable::setFront(QQuickItem *front) { Q_D(QQuickFlipable); if (d->front) { - qmlInfo(this) << tr("front is a write-once property"); + qmlWarning(this) << tr("front is a write-once property"); return; } d->front = front; @@ -175,7 +175,7 @@ void QQuickFlipable::setBack(QQuickItem *back) { Q_D(QQuickFlipable); if (d->back) { - qmlInfo(this) << tr("back is a write-once property"); + qmlWarning(this) << tr("back is a write-once property"); return; } if (back == 0) diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp index a6bf6b4e8a..22d631e917 100644 --- a/src/quick/items/qquickimagebase.cpp +++ b/src/quick/items/qquickimagebase.cpp @@ -281,7 +281,7 @@ void QQuickImageBase::requestFinished() Q_D(QQuickImageBase); if (d->pix.isError()) { - qmlInfo(this) << d->pix.error(); + qmlWarning(this) << d->pix.error(); d->pix.clear(this); d->status = Error; if (d->progress != 0.0) { diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 504446a8be..01737548c8 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -1566,7 +1566,7 @@ QQuickLayoutMirroringAttached::QQuickLayoutMirroringAttached(QObject *parent) : if (itemPrivate) itemPrivate->extra.value().layoutDirectionAttached = this; else - qmlInfo(parent) << tr("LayoutDirection attached property only works with Items and Windows"); + qmlWarning(parent) << tr("LayoutDirection attached property only works with Items and Windows"); } QQuickLayoutMirroringAttached * QQuickLayoutMirroringAttached::qmlAttachedProperties(QObject *object) @@ -1714,7 +1714,7 @@ QQuickEnterKeyAttached::QQuickEnterKeyAttached(QObject *parent) itemPrivate = QQuickItemPrivate::get(item); itemPrivate->extra.value().enterKeyAttached = this; } else - qmlInfo(parent) << tr("EnterKey attached property only works with Items"); + qmlWarning(parent) << tr("EnterKey attached property only works with Items"); } QQuickEnterKeyAttached *QQuickEnterKeyAttached::qmlAttachedProperties(QObject *object) @@ -4374,7 +4374,7 @@ void QQuickItem::mapFromItem(QQmlV4Function *args) const } if (!itemObj && !item->isNull()) { - qmlInfo(this) << "mapFromItem() given argument \"" << item->toQStringNoThrow() + qmlWarning(this) << "mapFromItem() given argument \"" << item->toQStringNoThrow() << "\" which is neither null nor an Item"; v4->throwTypeError(); return; @@ -4462,7 +4462,7 @@ void QQuickItem::mapToItem(QQmlV4Function *args) const } if (!itemObj && !item->isNull()) { - qmlInfo(this) << "mapToItem() given argument \"" << item->toQStringNoThrow() + qmlWarning(this) << "mapToItem() given argument \"" << item->toQStringNoThrow() << "\" which is neither null nor an Item"; v4->throwTypeError(); return; diff --git a/src/quick/items/qquickitemanimation.cpp b/src/quick/items/qquickitemanimation.cpp index fd4a7d733f..b33705e75e 100644 --- a/src/quick/items/qquickitemanimation.cpp +++ b/src/quick/items/qquickitemanimation.cpp @@ -304,7 +304,7 @@ QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &act bool ok; const QTransform &transform = targetParent->itemTransform(d->via, &ok); if (transform.type() >= QTransform::TxShear || !ok) { - qmlInfo(this) << QQuickParentAnimation::tr("Unable to preserve appearance under complex transform"); + qmlWarning(this) << QQuickParentAnimation::tr("Unable to preserve appearance under complex transform"); ok = false; } @@ -315,21 +315,21 @@ QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &act if (transform.m11() == transform.m22()) scale = transform.m11(); else { - qmlInfo(this) << QQuickParentAnimation::tr("Unable to preserve appearance under non-uniform scale"); + qmlWarning(this) << QQuickParentAnimation::tr("Unable to preserve appearance under non-uniform scale"); ok = false; } } else if (ok && isRotate) { if (transform.m11() == transform.m22()) scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12()); else { - qmlInfo(this) << QQuickParentAnimation::tr("Unable to preserve appearance under non-uniform scale"); + qmlWarning(this) << QQuickParentAnimation::tr("Unable to preserve appearance under non-uniform scale"); ok = false; } if (scale != 0) rotation = qAtan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI; else { - qmlInfo(this) << QQuickParentAnimation::tr("Unable to preserve appearance under scale of 0"); + qmlWarning(this) << QQuickParentAnimation::tr("Unable to preserve appearance under scale of 0"); ok = false; } } @@ -474,7 +474,7 @@ int QQuickAnchorAnimation::duration() const void QQuickAnchorAnimation::setDuration(int duration) { if (duration < 0) { - qmlInfo(this) << tr("Cannot set a duration of < 0"); + qmlWarning(this) << tr("Cannot set a duration of < 0"); return; } @@ -613,7 +613,7 @@ int QQuickPathAnimation::duration() const void QQuickPathAnimation::setDuration(int duration) { if (duration < 0) { - qmlInfo(this) << tr("Cannot set a duration of < 0"); + qmlWarning(this) << tr("Cannot set a duration of < 0"); return; } diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 7d98cc2693..3f097d4bc8 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -487,7 +487,7 @@ void QQuickItemView::setCacheBuffer(int b) { Q_D(QQuickItemView); if (b < 0) { - qmlInfo(this) << "Cannot set a negative cache buffer"; + qmlWarning(this) << "Cannot set a negative cache buffer"; return; } @@ -2345,7 +2345,7 @@ FxViewItem *QQuickItemViewPrivate::createItem(int modelIndex, bool asynchronous) if (!delegateValidated) { delegateValidated = true; QObject* delegate = q->delegate(); - qmlInfo(delegate ? delegate : q) << QQuickItemView::tr("Delegate must be of Item type"); + qmlWarning(delegate ? delegate : q) << QQuickItemView::tr("Delegate must be of Item type"); } } inRequest = false; diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp index eeec562e3c..5d5934bbd2 100644 --- a/src/quick/items/qquickloader.cpp +++ b/src/quick/items/qquickloader.cpp @@ -971,7 +971,7 @@ QV4::ReturnedValue QQuickLoaderPrivate::extractInitialPropertyValues(QQmlV4Funct QV4::ScopedValue v(scope, (*args)[1]); if (!v->isObject() || v->as()) { *error = true; - qmlInfo(loader) << QQuickLoader::tr("setSource: value is not an object"); + qmlWarning(loader) << QQuickLoader::tr("setSource: value is not an object"); } else { *error = false; valuemap = v; diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index 03596f13e9..53e547fe98 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -137,7 +137,7 @@ QQuickItem *QQuickPathViewPrivate::getItem(int modelIndex, qreal z, bool async) if (!delegateValidated) { delegateValidated = true; QObject* delegate = q->delegate(); - qmlInfo(delegate ? delegate : q) << QQuickPathView::tr("Delegate must be of Item type"); + qmlWarning(delegate ? delegate : q) << QQuickPathView::tr("Delegate must be of Item type"); } } } else { diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp index e22427ca49..0287fdd45c 100644 --- a/src/quick/items/qquickpositioners.cpp +++ b/src/quick/items/qquickpositioners.cpp @@ -957,7 +957,7 @@ void QQuickColumn::reportConflictingAnchors() } } if (d->anchorConflict) { - qmlInfo(this) << "Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column." + qmlWarning(this) << "Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column." << " Column will not function."; } } @@ -1224,7 +1224,7 @@ void QQuickRow::reportConflictingAnchors() } } if (d->anchorConflict) - qmlInfo(this) << "Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row." + qmlWarning(this) << "Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row." << " Row will not function."; } @@ -1808,7 +1808,7 @@ void QQuickGrid::reportConflictingAnchors() } } if (d->anchorConflict) - qmlInfo(this) << "Cannot specify anchors for items inside Grid." << " Grid will not function."; + qmlWarning(this) << "Cannot specify anchors for items inside Grid." << " Grid will not function."; } /*! @@ -2121,7 +2121,7 @@ void QQuickFlow::reportConflictingAnchors() } } if (d->anchorConflict) - qmlInfo(this) << "Cannot specify anchors for items inside Flow." << " Flow will not function."; + qmlWarning(this) << "Cannot specify anchors for items inside Flow." << " Flow will not function."; } QT_END_NAMESPACE diff --git a/src/quick/items/qquickrepeater.cpp b/src/quick/items/qquickrepeater.cpp index 4f46f41b0d..a7254464ed 100644 --- a/src/quick/items/qquickrepeater.cpp +++ b/src/quick/items/qquickrepeater.cpp @@ -423,7 +423,7 @@ void QQuickRepeater::initItem(int index, QObject *object) if (!d->delegateValidated) { d->delegateValidated = true; QObject* delegate = this->delegate(); - qmlInfo(delegate ? delegate : this) << QQuickRepeater::tr("Delegate must be of Item type"); + qmlWarning(delegate ? delegate : this) << QQuickRepeater::tr("Delegate must be of Item type"); } } return; diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp index f54a8911b2..d26a1f8a64 100644 --- a/src/quick/items/qquickspriteengine.cpp +++ b/src/quick/items/qquickspriteengine.cpp @@ -378,7 +378,7 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) if (!m_errorsPrinted && stat == QQuickPixmap::Error) { for (QQuickSprite* s : qAsConst(m_sprites)) if (s->m_pix.isError()) - qmlInfo(s) << s->m_pix.error(); + qmlWarning(s) << s->m_pix.error(); m_errorsPrinted = true; } @@ -399,7 +399,7 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) { const QSize frameSize(state->m_frameWidth, state->m_frameHeight); if (!(img.size() - frameSize).isValid()) { - qmlInfo(state).nospace() << "SpriteEngine: Invalid frame size " << frameSize << "." + qmlWarning(state).nospace() << "SpriteEngine: Invalid frame size " << frameSize << "." " It's bigger than image size " << img.size() << "."; return QImage(); } @@ -419,10 +419,10 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) int rowsNeeded = helper::divRoundUp(state->frames(), (maxSize / state->frameWidth())); if (h + rowsNeeded * state->frameHeight() > maxSize){ if (rowsNeeded * state->frameHeight() > maxSize) - qmlInfo(state) << "SpriteEngine: Animation too large to fit in one texture:" << state->source().toLocalFile(); + qmlWarning(state) << "SpriteEngine: Animation too large to fit in one texture:" << state->source().toLocalFile(); else - qmlInfo(state) << "SpriteEngine: Animations too large to fit in one texture, pushed over the edge by:" << state->source().toLocalFile(); - qmlInfo(state) << "SpriteEngine: Your texture max size today is " << maxSize; + qmlWarning(state) << "SpriteEngine: Animations too large to fit in one texture, pushed over the edge by:" << state->source().toLocalFile(); + qmlWarning(state) << "SpriteEngine: Your texture max size today is " << maxSize; return QImage(); } state->m_generatedCount = rowsNeeded; diff --git a/src/quick/items/qquickspritesequence.cpp b/src/quick/items/qquickspritesequence.cpp index 25a39f951a..858a3c0576 100644 --- a/src/quick/items/qquickspritesequence.cpp +++ b/src/quick/items/qquickspritesequence.cpp @@ -209,7 +209,7 @@ QSGSpriteNode *QQuickSpriteSequence::initNode() Q_D(QQuickSpriteSequence); if (!d->m_spriteEngine) { - qmlInfo(this) << "No sprite engine..."; + qmlWarning(this) << "No sprite engine..."; return nullptr; } else if (d->m_spriteEngine->status() == QQuickPixmap::Null) { d->m_spriteEngine->startAssemblingImage(); diff --git a/src/quick/items/qquickstateoperations.cpp b/src/quick/items/qquickstateoperations.cpp index 9cd3b6a5f5..b40a9e2843 100644 --- a/src/quick/items/qquickstateoperations.cpp +++ b/src/quick/items/qquickstateoperations.cpp @@ -78,7 +78,7 @@ void QQuickParentChangePrivate::doChange(QQuickItem *targetParent, QQuickItem *s bool ok; const QTransform &transform = target->parentItem()->itemTransform(targetParent, &ok); if (transform.type() >= QTransform::TxShear || !ok) { - qmlInfo(q) << QQuickParentChange::tr("Unable to preserve appearance under complex transform"); + qmlWarning(q) << QQuickParentChange::tr("Unable to preserve appearance under complex transform"); ok = false; } @@ -89,21 +89,21 @@ void QQuickParentChangePrivate::doChange(QQuickItem *targetParent, QQuickItem *s if (transform.m11() == transform.m22()) scale = transform.m11(); else { - qmlInfo(q) << QQuickParentChange::tr("Unable to preserve appearance under non-uniform scale"); + qmlWarning(q) << QQuickParentChange::tr("Unable to preserve appearance under non-uniform scale"); ok = false; } } else if (ok && isRotate) { if (transform.m11() == transform.m22()) scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12()); else { - qmlInfo(q) << QQuickParentChange::tr("Unable to preserve appearance under non-uniform scale"); + qmlWarning(q) << QQuickParentChange::tr("Unable to preserve appearance under non-uniform scale"); ok = false; } if (scale != 0) rotation = qAtan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI; else { - qmlInfo(q) << QQuickParentChange::tr("Unable to preserve appearance under scale of 0"); + qmlWarning(q) << QQuickParentChange::tr("Unable to preserve appearance under scale of 0"); ok = false; } } diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index e37a7e6d5e..30e9c71143 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -1135,7 +1135,7 @@ void QQuickTextPrivate::setLineGeometry(QTextLine &line, qreal lineWidth, qreal needToUpdateLayout = true; } } else if (image->pix->isError()) { - qmlInfo(q) << image->pix->error(); + qmlWarning(q) << image->pix->error(); } } diff --git a/src/quick/items/qquicktextdocument.cpp b/src/quick/items/qquicktextdocument.cpp index 61d75fe99b..c272503480 100644 --- a/src/quick/items/qquicktextdocument.cpp +++ b/src/quick/items/qquicktextdocument.cpp @@ -211,7 +211,7 @@ QQuickPixmap *QQuickTextDocumentWithImageResources::loadPixmap( if (p->isError()) { if (!errors.contains(url)) { errors.insert(url); - qmlInfo(parent()) << p->error(); + qmlWarning(parent()) << p->error(); } } return p; diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index 106acf57cf..8532786a8d 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -1741,7 +1741,7 @@ void QQuickTextEdit::select(int start, int end) bool QQuickTextEdit::isRightToLeft(int start, int end) { if (start > end) { - qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start."; + qmlWarning(this) << "isRightToLeft(start, end) called with the end property being smaller than the start."; return false; } else { return getText(start, end).isRightToLeft(); diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index e9f88ae7f0..a023ad8a8c 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -2002,7 +2002,7 @@ void QQuickTextInput::selectAll() bool QQuickTextInput::isRightToLeft(int start, int end) { if (start > end) { - qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start."; + qmlWarning(this) << "isRightToLeft(start, end) called with the end property being smaller than the start."; return false; } else { return text().midRef(start, end - start).isRightToLeft(); diff --git a/src/quick/items/qquicktextutil.cpp b/src/quick/items/qquicktextutil.cpp index 8bcdb0b5f6..b07289f4a3 100644 --- a/src/quick/items/qquicktextutil.cpp +++ b/src/quick/items/qquicktextutil.cpp @@ -61,7 +61,7 @@ QQuickItem *QQuickTextUtil::createCursor( item->setPosition(rectangle.topLeft()); item->setHeight(rectangle.height()); } else { - qmlInfo(parent) << tr("%1 does not support loading non-visual cursor delegates.") + qmlWarning(parent) << tr("%1 does not support loading non-visual cursor delegates.") .arg(QString::fromUtf8(className)); } component->completeCreate(); @@ -72,7 +72,7 @@ QQuickItem *QQuickTextUtil::createCursor( parent, SLOT(createCursor()), Qt::UniqueConnection); return item; } - qmlInfo(parent, component->errors()) << tr("Could not load cursor delegate"); + qmlWarning(parent, component->errors()) << tr("Could not load cursor delegate"); return item; } diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp index 9de474ac36..1a2441171d 100644 --- a/src/quick/util/qquickanimation.cpp +++ b/src/quick/util/qquickanimation.cpp @@ -192,14 +192,14 @@ QQmlProperty QQuickAbstractAnimationPrivate::createProperty(QObject *obj, const if (errorMessage) *errorMessage = message; else - qmlInfo(infoObj) << message; + qmlWarning(infoObj) << message; return QQmlProperty(); } else if (!prop.isWritable()) { const QString message = QQuickAbstractAnimation::tr("Cannot animate read-only property \"%1\"").arg(str); if (errorMessage) *errorMessage = message; else - qmlInfo(infoObj) << message; + qmlWarning(infoObj) << message; return QQmlProperty(); } return prop; @@ -256,7 +256,7 @@ void QQuickAbstractAnimation::setRunning(bool r) return; if (d->group || d->disableUserControl) { - qmlInfo(this) << "setRunning() cannot be used on non-root animation nodes."; + qmlWarning(this) << "setRunning() cannot be used on non-root animation nodes."; return; } @@ -322,12 +322,12 @@ void QQuickAbstractAnimation::setPaused(bool p) return; if (!d->running) { - qmlInfo(this) << "setPaused() cannot be used when animation isn't running."; + qmlWarning(this) << "setPaused() cannot be used when animation isn't running."; return; } if (d->group || d->disableUserControl) { - qmlInfo(this) << "setPaused() cannot be used on non-root animation nodes."; + qmlWarning(this) << "setPaused() cannot be used on non-root animation nodes."; return; } @@ -709,7 +709,7 @@ int QQuickPauseAnimation::duration() const void QQuickPauseAnimation::setDuration(int duration) { if (duration < 0) { - qmlInfo(this) << tr("Cannot set a duration of < 0"); + qmlWarning(this) << tr("Cannot set a duration of < 0"); return; } @@ -1004,7 +1004,7 @@ void QQuickScriptActionPrivate::execute() QQmlExpression expr(scriptStr); expr.evaluate(); if (expr.hasError()) - qmlInfo(q) << expr.error(); + qmlWarning(q) << expr.error(); } } @@ -2077,7 +2077,7 @@ int QQuickPropertyAnimation::duration() const void QQuickPropertyAnimation::setDuration(int duration) { if (duration < 0) { - qmlInfo(this) << tr("Cannot set a duration of < 0"); + qmlWarning(this) << tr("Cannot set a duration of < 0"); return; } @@ -2644,7 +2644,7 @@ QQuickStateActions QQuickPropertyAnimation::createTransitionActions(QQuickStateA if (!successfullyCreatedDefaultProperty) { for (const QString &errorMessage : qAsConst(errorMessages)) - qmlInfo(this) << errorMessage; + qmlWarning(this) << errorMessage; } } diff --git a/src/quick/util/qquickanimationcontroller.cpp b/src/quick/util/qquickanimationcontroller.cpp index 4bc2d6319e..fa1ade50d1 100644 --- a/src/quick/util/qquickanimationcontroller.cpp +++ b/src/quick/util/qquickanimationcontroller.cpp @@ -169,7 +169,7 @@ void QQuickAnimationController::setAnimation(QQuickAbstractAnimation *animation) if (animation != d->animation) { if (animation) { if (animation->userControlDisabled()) { - qmlInfo(this) << "QQuickAnimationController::setAnimation: the animation is controlled by others, can't be used in AnimationController."; + qmlWarning(this) << "QQuickAnimationController::setAnimation: the animation is controlled by others, can't be used in AnimationController."; return; } animation->setDisableUserControl(); diff --git a/src/quick/util/qquickbehavior.cpp b/src/quick/util/qquickbehavior.cpp index 9af1d41b29..1b2d9afb7c 100644 --- a/src/quick/util/qquickbehavior.cpp +++ b/src/quick/util/qquickbehavior.cpp @@ -129,7 +129,7 @@ void QQuickBehavior::setAnimation(QQuickAbstractAnimation *animation) { Q_D(QQuickBehavior); if (d->animation) { - qmlInfo(this) << tr("Cannot change the animation assigned to a Behavior."); + qmlWarning(this) << tr("Cannot change the animation assigned to a Behavior."); return; } diff --git a/src/quick/util/qquickfontloader.cpp b/src/quick/util/qquickfontloader.cpp index d13291c30a..3761a37a6d 100644 --- a/src/quick/util/qquickfontloader.cpp +++ b/src/quick/util/qquickfontloader.cpp @@ -307,7 +307,7 @@ void QQuickFontLoader::updateFontInfo(const QString& name, QQuickFontLoader::Sta } if (status != d->status) { if (status == Error) - qmlInfo(this) << "Cannot load font: \"" << d->url.toString() << '"'; + qmlWarning(this) << "Cannot load font: \"" << d->url.toString() << '"'; d->status = status; emit statusChanged(); } diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp index fafa2edd0b..20aa52e472 100644 --- a/src/quick/util/qquickpropertychanges.cpp +++ b/src/quick/util/qquickpropertychanges.cpp @@ -397,10 +397,10 @@ QQuickPropertyChangesPrivate::property(const QString &property) Q_Q(QQuickPropertyChanges); QQmlProperty prop(object, property, qmlContext(q)); if (!prop.isValid()) { - qmlInfo(q) << QQuickPropertyChanges::tr("Cannot assign to non-existent property \"%1\"").arg(property); + qmlWarning(q) << QQuickPropertyChanges::tr("Cannot assign to non-existent property \"%1\"").arg(property); return QQmlProperty(); } else if (!(prop.type() & QQmlProperty::SignalProperty) && !prop.isWritable()) { - qmlInfo(q) << QQuickPropertyChanges::tr("Cannot assign to read-only property \"%1\"").arg(property); + qmlWarning(q) << QQuickPropertyChanges::tr("Cannot assign to read-only property \"%1\"").arg(property); return QQmlProperty(); } return prop; diff --git a/src/quick/util/qquickstatechangescript.cpp b/src/quick/util/qquickstatechangescript.cpp index 86b70fe879..a70fa1a676 100644 --- a/src/quick/util/qquickstatechangescript.cpp +++ b/src/quick/util/qquickstatechangescript.cpp @@ -131,7 +131,7 @@ void QQuickStateChangeScript::execute() QQmlExpression expr(d->script); expr.evaluate(); if (expr.hasError()) - qmlInfo(this, expr.error()); + qmlWarning(this, expr.error()); } } diff --git a/src/quick/util/qquickstategroup.cpp b/src/quick/util/qquickstategroup.cpp index 200f243a1b..f2cd4638fc 100644 --- a/src/quick/util/qquickstategroup.cpp +++ b/src/quick/util/qquickstategroup.cpp @@ -438,7 +438,7 @@ void QQuickStateGroupPrivate::setCurrentStateInternal(const QString &state, } if (applyingState) { - qmlInfo(q) << "Can't apply a state change as part of a state definition."; + qmlWarning(q) << "Can't apply a state change as part of a state definition."; return; } -- cgit v1.2.3 From 105f5dc352dd866844fad80a510105e5e7a70e9b Mon Sep 17 00:00:00 2001 From: Pier Luigi Fiorini Date: Tue, 10 Jan 2017 07:59:06 +0100 Subject: QSGNodeVisitorEx virtual destructor QSGNodeVisitorEx has virtual methods and accessible non-virtual destructor. Change-Id: I38ebfb07acee4aa433623db5f623ced03995f442 Reviewed-by: Shawn Rutledge Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/qsgadaptationlayer_p.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h index bf267ccf92..03a1f7f281 100644 --- a/src/quick/scenegraph/qsgadaptationlayer_p.h +++ b/src/quick/scenegraph/qsgadaptationlayer_p.h @@ -87,6 +87,8 @@ class QSGRenderNode; class Q_QUICK_PRIVATE_EXPORT QSGNodeVisitorEx { public: + virtual ~QSGNodeVisitorEx() {} + // visit(...) returns true if the children are supposed to be // visisted and false if they're supposed to be skipped by the visitor. -- cgit v1.2.3 From a16f2cc391c0be5614641e629267bcbf4d200951 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Wed, 11 Jan 2017 16:11:18 +0100 Subject: test: fix tst_QQuickGraphicsInfo::testProperties() This also reverts commit 26051fd5724e56e0715bc56fde8e8464ff386bbc. Task-number: QTBUG-58039 Change-Id: I0b9146a64f1a112f5c059b2e29e874631c81d12c Reviewed-by: David Faure --- tests/auto/quick/qquickgraphicsinfo/BLACKLIST | 3 --- tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 tests/auto/quick/qquickgraphicsinfo/BLACKLIST diff --git a/tests/auto/quick/qquickgraphicsinfo/BLACKLIST b/tests/auto/quick/qquickgraphicsinfo/BLACKLIST deleted file mode 100644 index 4cefc165f0..0000000000 --- a/tests/auto/quick/qquickgraphicsinfo/BLACKLIST +++ /dev/null @@ -1,3 +0,0 @@ -[tst_QQuickGraphicsInfo::testProperties] -opensuse-42.1 -ubuntu-14.04 diff --git a/tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp b/tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp index 650892d650..4da6da6043 100644 --- a/tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp +++ b/tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp @@ -51,7 +51,7 @@ private slots: void tst_QQuickGraphicsInfo::testProperties() { QQuickView view; - view.setSource(QUrl::fromLocalFile("data/basic.qml")); + view.setSource(QUrl("data/basic.qml")); view.show(); QVERIFY(QTest::qWaitForWindowExposed(&view)); -- cgit v1.2.3 From 342c72da64cac4aec1463091f6fe0bfb16cd1850 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Thu, 5 Jan 2017 13:42:14 +0100 Subject: Avoid needless notifications when destroying layouts When deleting a layout with children, it ends up in ~QQuickItem(), which in turn will call setParentItem(0). setParentItem(0) will in turn call setEffectiveVisibleRecur(), which will recurse down all its descendants. Therefore, deleting a top level layout might trigger item change listeners for *all* its descendants, not only its direct children. This behavior might even cause crashes: The visibility changes will then trigger an invalidation of the layout, which will propagate up the parent hierarchy, and potentially call invalidate() on a partially-destroyed layout, which then might crash. Change-Id: I48e11d57f69e9011ced6c3a0b51e3d89b24ad5c1 Task-number: QTBUG-55103 Reviewed-by: Shawn Rutledge --- src/imports/layouts/qquicklayout.cpp | 26 ++++++++++++++++++++++ src/imports/layouts/qquicklayout_p.h | 2 ++ src/imports/layouts/qquicklinearlayout.cpp | 6 +---- .../quick/qquicklayouts/data/tst_rowlayout.qml | 21 +++++++++++++++++ 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/imports/layouts/qquicklayout.cpp b/src/imports/layouts/qquicklayout.cpp index 3786d21727..fd2ff4a73e 100644 --- a/src/imports/layouts/qquicklayout.cpp +++ b/src/imports/layouts/qquicklayout.cpp @@ -762,9 +762,11 @@ bool QQuickLayout::shouldIgnoreItem(QQuickItem *child, QQuickLayoutAttached *&in void QQuickLayout::itemChange(ItemChange change, const ItemChangeData &value) { if (change == ItemChildAddedChange) { + Q_D(QQuickLayout); QQuickItem *item = value.item; qmlobject_connect(item, QQuickItem, SIGNAL(baselineOffsetChanged(qreal)), this, QQuickLayout, SLOT(invalidateSenderItem())); QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::SiblingOrder | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight | QQuickItemPrivate::Destroyed | QQuickItemPrivate::Visibility); + d->m_hasItemChangeListeners = true; if (isReady()) updateLayoutItems(); } else if (change == ItemChildRemovedChange) { @@ -802,6 +804,30 @@ bool QQuickLayout::isReady() const return d_func()->m_isReady; } +/*! + * \brief QQuickLayout::deactivateRecur + * \internal + * + * Call this from the dtor of the top-level layout. + * Otherwise, it will trigger lots of unneeded item change listeners (itemVisibleChanged()) for all its descendants + * that will have its impact thrown away. + */ +void QQuickLayout::deactivateRecur() +{ + if (d_func()->m_hasItemChangeListeners) { + for (int i = 0; i < itemCount(); ++i) { + QQuickItem *item = itemAt(i); + // When deleting a layout with children, there is no reason for the children to inform the layout that their + // e.g. visibility got changed. The layout already knows that all its children will eventually become invisible, so + // we therefore remove its change listener. + QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::SiblingOrder | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight | QQuickItemPrivate::Destroyed | QQuickItemPrivate::Visibility); + if (QQuickLayout *layout = qobject_cast(item)) + layout->deactivateRecur(); + } + d_func()->m_hasItemChangeListeners = false; + } +} + void QQuickLayout::itemSiblingOrderChanged(QQuickItem *item) { Q_UNUSED(item); diff --git a/src/imports/layouts/qquicklayout_p.h b/src/imports/layouts/qquicklayout_p.h index eece6f8658..113498eb2b 100644 --- a/src/imports/layouts/qquicklayout_p.h +++ b/src/imports/layouts/qquicklayout_p.h @@ -95,6 +95,7 @@ public: void itemChange(ItemChange change, const ItemChangeData &value) Q_DECL_OVERRIDE; void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; bool isReady() const; + void deactivateRecur(); /* QQuickItemChangeListener */ @@ -134,6 +135,7 @@ public: protected: unsigned m_isReady : 1; unsigned m_disableRearrange : 1; + unsigned m_hasItemChangeListeners : 1; // if false, we don't need to remove its item change listeners... mutable QSet m_ignoredItems; }; diff --git a/src/imports/layouts/qquicklinearlayout.cpp b/src/imports/layouts/qquicklinearlayout.cpp index 13fdd496c2..50b3eed87e 100644 --- a/src/imports/layouts/qquicklinearlayout.cpp +++ b/src/imports/layouts/qquicklinearlayout.cpp @@ -305,11 +305,7 @@ QQuickGridLayoutBase::~QQuickGridLayoutBase() // Remove item listeners so we do not act on signalling unnecessarily // (there is no point, as the layout will be torn down anyway). - for (int i = 0; i < itemCount(); ++i) { - QQuickItem *item = itemAt(i); - QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::SiblingOrder | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight | QQuickItemPrivate::Destroyed | QQuickItemPrivate::Visibility); - } - + deactivateRecur(); delete d->styleInfo; } diff --git a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml index 2d4e227a9e..97860458fe 100644 --- a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml +++ b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml @@ -802,6 +802,27 @@ Item { layout.destroy() // Do not crash } + Component { + id: rectangle_Component + Rectangle { + width: 100 + height: 50 + } + } + + function test_destroyImplicitInvisibleLayout() + { + var root = rectangle_Component.createObject(container) + root.visible = false + var layout = layout_deleteLayout.createObject(root) + layout.visible = true + // at this point the layout is still invisible because root is invisible + layout.destroy() + // Do not crash when destructing the layout + waitForRendering(container) // should ideally call gc(), but does not work + root.destroy() + } + function test_sizeHintWithHiddenChildren(data) { var layout = layout_sizeHint_Component.createObject(container) var grid = layout.children[0] -- cgit v1.2.3 From 770915841def879301e58496caf4b552a86a6103 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sun, 11 Dec 2016 17:04:50 +0100 Subject: Update QSGRenderNode docs to match reality Scissor and stencil tests are not actually enabled when invoking render(), meaning rendernode implementations do not clip by default. This has been documented when making the class public in 5.8, but the older list with the OpenGL states still contains contradictory entries which are false since Qt 5.2 or so. Change-Id: I46875b11322585d40962db2c4302602a1410a7b9 Reviewed-by: Andy Nichols --- src/quick/scenegraph/coreapi/qsgrendernode.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.cpp b/src/quick/scenegraph/coreapi/qsgrendernode.cpp index 5915d51f2b..1bc0210b72 100644 --- a/src/quick/scenegraph/coreapi/qsgrendernode.cpp +++ b/src/quick/scenegraph/coreapi/qsgrendernode.cpp @@ -160,10 +160,7 @@ QSGRenderNode::StateFlags QSGRenderNode::changedStates() const \list \li glDepthMask(false) \li glDisable(GL_DEPTH_TEST) - \li glStencilMask(0) - \li glEnable(GL_STENCIL_TEST)/glDisable(GL_STENCIL_TEST) depending on clip \li glStencilFunc(GL_EQUAL, state.stencilValue, 0xff) depending on clip - \li glEnable(GL_SCISSOR_TEST)/glDisable(GL_SCISSOR_TEST) depending on clip \li glScissor(state.scissorRect.x(), state.scissorRect.y(), state.scissorRect.width(), state.scissorRect.height()) depending on clip \li glEnable(GL_BLEND) -- cgit v1.2.3 From 1cead4f316184489ff81e689611b91d3760ee5cf Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 13 Dec 2016 14:24:49 +0100 Subject: Propagate root changes to rendernodes too Otherwise weird things will happen once a node gets turned into a batch root and the rendernodes in the child subtree still refers to their old root. Change-Id: I42b0ba514c2fbeed833f0f665e49b275c19b5686 Reviewed-by: Andy Nichols --- src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 4893c175a3..8d4c313056 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -979,6 +979,10 @@ void Renderer::nodeChangedBatchRoot(Node *node, Node *root) e->root = root; e->boundsComputed = false; } + } else if (node->type() == QSGNode::RenderNodeType) { + RenderNodeElement *e = node->renderNodeElement(); + if (e) + e->root = root; } SHADOWNODE_TRAVERSE(node) -- cgit v1.2.3 From 9ce6712c981c312f5c417c58b0d578d872af428a Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 6 Dec 2016 14:35:56 +0100 Subject: Fix projection matrix for DepthAware QSGRenderNodes Unlike renderUnmergedBatches(), renderRenderNode() did not adjust the projection matrix. Change-Id: Ib5a7183a3623d35c85af47205cc22187bad89409 Reviewed-by: Andy Nichols --- src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 8d4c313056..d4324bc489 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -2803,8 +2803,13 @@ void Renderer::renderRenderNode(Batch *batch) updateClip(rd->m_clip_list, batch); - RenderNodeState state; QMatrix4x4 pm = projectionMatrix(); + if (m_useDepthBuffer) { + pm(2, 2) = m_zRange; + pm(2, 3) = 1.0f - e->order * m_zRange; + } + + RenderNodeState state; state.m_projectionMatrix = ± state.m_scissorEnabled = m_currentClipType & ScissorClip; state.m_stencilEnabled = m_currentClipType & StencilClip; -- cgit v1.2.3 From fd0d4464533ae773a5b70cb803b25fd97b6f09a0 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 11 Jan 2017 21:08:23 +0100 Subject: QJSValue: Mention how to construct QJSValue from other non-obvious types This has come up in queries from users, so let's add a helping hand. Change-Id: If4e5efdd8969a71a78fc88ae168ede8d681858aa Reviewed-by: Simon Hausmann --- src/qml/jsapi/qjsvalue.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index b473e96286..bab2e633a7 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -73,7 +73,8 @@ For the object-based types (including Date and RegExp), use the newT() functions in QJSEngine (e.g. QJSEngine::newObject()) to create a QJSValue of the desired type. For the primitive types, - use one of the QJSValue constructor overloads. + use one of the QJSValue constructor overloads. For other types, e.g. + registered gadget types such as QPoint, you can use QJSEngine::toScriptValue. The methods named isT() (e.g. isBool(), isUndefined()) can be used to test if a value is of a certain type. The methods named -- cgit v1.2.3 From c2e46b9d9140903f5b563f8835c11d4491452405 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Thu, 5 Jan 2017 20:19:29 +0100 Subject: QQuickItemGrabResult: Use qmlWarning instead of qWarning This way we have information on the source location of the call instead of flying blind and having to grep (possibly many) codebases to find the offender. Change-Id: I86fb1b4a475ed2df7812890c7ee37246735d5a60 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickitemgrabresult.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/quick/items/qquickitemgrabresult.cpp b/src/quick/items/qquickitemgrabresult.cpp index c6355ceed2..07c2cb607c 100644 --- a/src/quick/items/qquickitemgrabresult.cpp +++ b/src/quick/items/qquickitemgrabresult.cpp @@ -47,6 +47,7 @@ #endif #include +#include #include #include @@ -279,17 +280,17 @@ QQuickItemGrabResult *QQuickItemGrabResultPrivate::create(QQuickItem *item, cons size = QSize(item->width(), item->height()); if (size.width() < 1 || size.height() < 1) { - qWarning("Item::grabToImage: item has invalid dimensions"); + qmlWarning(item) << "grabToImage: item has invalid dimensions"; return 0; } if (!item->window()) { - qWarning("Item::grabToImage: item is not attached to a window"); + qmlWarning(item) << "grabToImage: item is not attached to a window"; return 0; } if (!item->window()->isVisible()) { - qWarning("Item::grabToImage: item's window is not visible"); + qmlWarning(item) << "grabToImage: item's window is not visible"; return 0; } @@ -377,12 +378,12 @@ bool QQuickItem::grabToImage(const QJSValue &callback, const QSize &targetSize) { QQmlEngine *engine = qmlEngine(this); if (!engine) { - qWarning("Item::grabToImage: no QML Engine"); + qmlWarning(this) << "grabToImage: item has no QML engine"; return false; } if (!callback.isCallable()) { - qWarning("Item::grabToImage: 'callback' is not a function"); + qmlWarning(this) << "grabToImage: 'callback' is not a function"; return false; } @@ -391,12 +392,12 @@ bool QQuickItem::grabToImage(const QJSValue &callback, const QSize &targetSize) size = QSize(width(), height()); if (size.width() < 1 || size.height() < 1) { - qWarning("Item::grabToImage: item has invalid dimensions"); + qmlWarning(this) << "grabToImage: item has invalid dimensions"; return false; } if (!window()) { - qWarning("Item::grabToImage: item is not attached to a window"); + qmlWarning(this) << "grabToImage: item is not attached to a window"; return false; } -- cgit v1.2.3 From 93df3e3a3118080dcd6d9416d1622b88d99c4b8d Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 11 Jan 2017 23:29:23 +0100 Subject: QSGThreadedRenderLoop: Correctly stop the animation timer ... ... when destroying the last window while it is still visible. For the case of windowDestroyed(), the QQuickWindow can still be isVisible true and isExposed true. Given these circumstances, we would not stop the timer (assuming that we needed to keep it running), but this is actually wrong when we are evaluating a timer change depending on the window being destroyed. By calling startOrStopAnimationTimer again, after the window has been removed from m_windows, we will successfully stop the timer -- the only cost being an unnecessary polish event being sent from the first call (which will be ignored). Task-number: QTBUG-58091 Change-Id: I043ce5d88eafee15019e1c8d41c06d531d1da059 Reviewed-by: Gunnar Sletta --- src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp | 5 +++++ .../adaptations/software/qsgsoftwarethreadedrenderloop.cpp | 5 +++++ src/quick/scenegraph/qsgthreadedrenderloop.cpp | 8 +++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp index 317471eeec..11cc257103 100644 --- a/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp +++ b/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp @@ -773,6 +773,11 @@ void QSGD3D12ThreadedRenderLoop::windowDestroyed(QQuickWindow *window) break; } } + + // Now that we altered the window list, we may need to stop the animation + // timer even if we didn't via handleObscurity. This covers the case where + // we destroy a visible & exposed QQuickWindow. + startOrStopAnimationTimer(); } void QSGD3D12ThreadedRenderLoop::exposureChanged(QQuickWindow *window) diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp index df5ec9b745..8abbefdd48 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp @@ -618,6 +618,11 @@ void QSGSoftwareThreadedRenderLoop::windowDestroyed(QQuickWindow *window) break; } } + + // Now that we altered the window list, we may need to stop the animation + // timer even if we didn't via handleObscurity. This covers the case where + // we destroy a visible & exposed QQuickWindow. + startOrStopAnimationTimer(); } void QSGSoftwareThreadedRenderLoop::exposureChanged(QQuickWindow *window) diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 4543782d5b..cb5e17c71e 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -826,13 +826,14 @@ void QSGThreadedRenderLoop::startOrStopAnimationTimer() } if (m_animation_timer != 0 && (exposedWindows == 1 || !m_animation_driver->isRunning())) { + qCDebug(QSG_LOG_RENDERLOOP) << "*** Stopping animation timer"; killTimer(m_animation_timer); m_animation_timer = 0; // If animations are running, make sure we keep on animating if (m_animation_driver->isRunning()) maybePostPolishRequest(const_cast(theOne)); - } else if (m_animation_timer == 0 && exposedWindows != 1 && m_animation_driver->isRunning()) { + qCDebug(QSG_LOG_RENDERLOOP) << "*** Starting animation timer"; m_animation_timer = startTimer(qsgrl_animation_interval()); } } @@ -888,6 +889,11 @@ void QSGThreadedRenderLoop::windowDestroyed(QQuickWindow *window) } } + // Now that we altered the window list, we may need to stop the animation + // timer even if we didn't via handleObscurity. This covers the case where + // we destroy a visible & exposed QQuickWindow. + startOrStopAnimationTimer(); + qCDebug(QSG_LOG_RENDERLOOP) << "done windowDestroyed()" << window; } -- cgit v1.2.3 From 0820efecb48d241f46f13f72c688d809fab6b72d Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 21 Oct 2016 17:21:36 -0500 Subject: Improve visibility into Positioner positioning from QML Add a forceLayout function, similar to the views, as well as a signal that indicates when positioning has completed. Change-Id: Ice01ea0840c707e403fdd4ea59d92a89e2ed8e4b Task-number: QTBUG-44762 Task-number: QTBUG-32114 Reviewed-by: J-P Nurmi --- src/quick/items/qquickitemsmodule.cpp | 4 + src/quick/items/qquickpositioners.cpp | 93 ++++++++++++++++++++++ src/quick/items/qquickpositioners_p.h | 3 + tests/auto/qmltest/positioners/tst_positioners.qml | 75 +++++++++++++++++ 4 files changed, 175 insertions(+) create mode 100644 tests/auto/qmltest/positioners/tst_positioners.qml diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 0b325d7fa8..5bba52ed73 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -380,6 +380,10 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType(uri, 2, 9, "TouchPoint"); qRegisterMetaType("QPointingDeviceUniqueId"); qmlRegisterUncreatableType(uri, 2, 9, "PointingDeviceUniqueId", QQuickTouchPoint::tr("PointingDeviceUniqueId is only available via read-only properties")); +#if QT_CONFIG(quick_positioners) + qmlRegisterUncreatableType(uri, 2, 9, "Positioner", + QStringLiteral("Positioner is an abstract type that is only available as an attached property.")); +#endif } static void initResources() diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp index 0287fdd45c..05d3ae0191 100644 --- a/src/quick/items/qquickpositioners.cpp +++ b/src/quick/items/qquickpositioners.cpp @@ -290,6 +290,11 @@ void QQuickBasePositioner::itemChange(ItemChange change, const ItemChangeData &v QQuickItem::itemChange(change, value); } +void QQuickBasePositioner::forceLayout() +{ + updatePolish(); +} + void QQuickBasePositioner::prePositioning() { Q_D(QQuickBasePositioner); @@ -401,6 +406,8 @@ void QQuickBasePositioner::prePositioning() //Set implicit size to the size of its children setImplicitSize(contentSize.width(), contentSize.height()); + + emit positioningComplete(); } void QQuickBasePositioner::positionItem(qreal x, qreal y, PositionedItem *target) @@ -910,6 +917,28 @@ void QQuickPositionerAttached::setIsLastItem(bool isLastItem) \sa Grid::spacing */ +/*! + \qmlmethod QtQuick::Column::forceLayout() + \since 5.9 + + Column typically positions its children once per frame. This means that + inside script blocks it is possible for the underlying children to have changed, + but the Column to have not yet been updated accordingly. + + This method forces the Column to immediately respond to any outstanding + changes in its children. + + \b Note: methods in general should only be called after the Component has completed. +*/ +/*! + \qmlsignal QtQuick::Column::positioningComplete() + \since 5.9 + + This signal is emitted when positioning has been completed. + + The corresponding handler is \c onPositioningComplete. +*/ + QQuickColumn::QQuickColumn(QQuickItem *parent) : QQuickBasePositioner(Vertical, parent) { @@ -1077,6 +1106,27 @@ void QQuickColumn::reportConflictingAnchors() \sa Grid::spacing */ +/*! + \qmlmethod QtQuick::Row::forceLayout() + \since 5.9 + + Row typically positions its children once per frame. This means that + inside script blocks it is possible for the underlying children to have changed, + but the Row to have not yet been updated accordingly. + + This method forces the Row to immediately respond to any outstanding + changes in its children. + + \b Note: methods in general should only be called after the Component has completed. +*/ +/*! + \qmlsignal QtQuick::Row::positioningComplete() + \since 5.9 + + This signal is emitted when positioning has been completed. + + The corresponding handler is \c onPositioningComplete. +*/ class QQuickRowPrivate : public QQuickBasePositionerPrivate { @@ -1355,6 +1405,27 @@ void QQuickRow::reportConflictingAnchors() \sa rows, columns */ +/*! + \qmlmethod QtQuick::Grid::forceLayout() + \since 5.9 + + Grid typically positions its children once per frame. This means that + inside script blocks it is possible for the underlying children to have changed, + but the Grid to have not yet been updated accordingly. + + This method forces the Grid to immediately respond to any outstanding + changes in its children. + + \b Note: methods in general should only be called after the Component has completed. +*/ +/*! + \qmlsignal QtQuick::Grid::positioningComplete() + \since 5.9 + + This signal is emitted when positioning has been completed. + + The corresponding handler is \c onPositioningComplete. +*/ class QQuickGridPrivate : public QQuickBasePositionerPrivate { @@ -1920,6 +1991,28 @@ void QQuickGrid::reportConflictingAnchors() \sa Grid::spacing */ +/*! + \qmlmethod QtQuick::Flow::forceLayout() + \since 5.9 + + Flow typically positions its children once per frame. This means that + inside script blocks it is possible for the underlying children to have changed, + but the Flow to have not yet been updated accordingly. + + This method forces the Flow to immediately respond to any outstanding + changes in its children. + + + \b Note: methods in general should only be called after the Component has completed. +*/ +/*! + \qmlsignal QtQuick::Flow::positioningComplete() + \since 5.9 + + This signal is emitted when positioning has been completed. + + The corresponding handler is \c onPositioningComplete. +*/ class QQuickFlowPrivate : public QQuickBasePositionerPrivate { diff --git a/src/quick/items/qquickpositioners_p.h b/src/quick/items/qquickpositioners_p.h index c25ecd6dbc..ae6e795794 100644 --- a/src/quick/items/qquickpositioners_p.h +++ b/src/quick/items/qquickpositioners_p.h @@ -155,6 +155,8 @@ public: void setBottomPadding(qreal padding); void resetBottomPadding(); + Q_REVISION(9) Q_INVOKABLE void forceLayout(); + protected: QQuickBasePositioner(QQuickBasePositionerPrivate &dd, PositionerType at, QQuickItem *parent); void componentComplete() Q_DECL_OVERRIDE; @@ -172,6 +174,7 @@ Q_SIGNALS: Q_REVISION(6) void leftPaddingChanged(); Q_REVISION(6) void rightPaddingChanged(); Q_REVISION(6) void bottomPaddingChanged(); + Q_REVISION(9) void positioningComplete(); protected Q_SLOTS: void prePositioning(); diff --git a/tests/auto/qmltest/positioners/tst_positioners.qml b/tests/auto/qmltest/positioners/tst_positioners.qml new file mode 100644 index 0000000000..03a0e13225 --- /dev/null +++ b/tests/auto/qmltest/positioners/tst_positioners.qml @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtTest 1.1 + +Item { + Column { + id: column + Repeater { + id: repeater + model: 2 + Rectangle { + width: 100 + height: 30 + border.width: 1 + } + } + } + + SignalSpy { + id: spy + target: column + signalName: "positioningComplete" + } + + TestCase { + function test_forceLayout() { + compare(column.height, 60) + repeater.model = 4 + column.forceLayout() + compare(column.height, 120) + + // initial positioning and our forced layout + compare(spy.count, 2) + } + } +} -- cgit v1.2.3 From dcc2a07791243d0010d25f092da2d1747ae2f711 Mon Sep 17 00:00:00 2001 From: Kimmo Ollila Date: Thu, 12 Jan 2017 00:54:16 +0200 Subject: Add initial support for INTEGRITY Change-Id: I1b44263a700f6c48c3b7798b662b30b03f9a4dc4 Reviewed-by: Rolland Dudemaine Reviewed-by: Lars Knoll --- src/3rdparty/masm/assembler/MacroAssemblerCodeRef.h | 2 +- src/3rdparty/masm/wtf/Compiler.h | 5 +++++ src/3rdparty/masm/wtf/Platform.h | 16 +++++++++++++--- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/3rdparty/masm/assembler/MacroAssemblerCodeRef.h b/src/3rdparty/masm/assembler/MacroAssemblerCodeRef.h index f03254aa38..e3c77d99e6 100644 --- a/src/3rdparty/masm/assembler/MacroAssemblerCodeRef.h +++ b/src/3rdparty/masm/assembler/MacroAssemblerCodeRef.h @@ -66,7 +66,7 @@ #define CALLING_CONVENTION_IS_STDCALL 0 #endif -#if CPU(X86) +#if CPU(X86) && !OS(INTEGRITY) #define HAS_FASTCALL_CALLING_CONVENTION 1 #ifndef FASTCALL #if COMPILER(MSVC) diff --git a/src/3rdparty/masm/wtf/Compiler.h b/src/3rdparty/masm/wtf/Compiler.h index fc3b5c5c08..da10196cc1 100644 --- a/src/3rdparty/masm/wtf/Compiler.h +++ b/src/3rdparty/masm/wtf/Compiler.h @@ -113,6 +113,11 @@ #define GCCE_VERSION_AT_LEAST(major, minor, patch) (GCCE_VERSION >= (major * 10000 + minor * 100 + patch)) #endif +/* COMPILER(GHS) - Green Hills MULTI Compiler */ +#if defined(__ghs) +#define WTF_COMPILER_GHS 1 +#endif + /* COMPILER(GCC) - GNU Compiler Collection */ /* --gnu option of the RVCT compiler also defines __GNUC__ */ #if defined(__GNUC__) && !COMPILER(RVCT) diff --git a/src/3rdparty/masm/wtf/Platform.h b/src/3rdparty/masm/wtf/Platform.h index 3f480d344a..bc62c381db 100644 --- a/src/3rdparty/masm/wtf/Platform.h +++ b/src/3rdparty/masm/wtf/Platform.h @@ -224,7 +224,8 @@ #elif defined(__ARM_ARCH_7A__) \ || defined(__ARM_ARCH_7R__) \ - || defined(__ARM_ARCH_7S__) + || defined(__ARM_ARCH_7S__) \ + || defined(__CORE_CORTEXA__) // GHS-specific #define WTF_ARM_ARCH_VERSION 7 /* MSVC sets _M_ARM */ @@ -268,7 +269,8 @@ || defined(__ARM_ARCH_7A__) \ || defined(__ARM_ARCH_7M__) \ || defined(__ARM_ARCH_7R__) \ - || defined(__ARM_ARCH_7S__) + || defined(__ARM_ARCH_7S__) \ + || defined(__CORE_CORTEXA__) // GHS-specific #define WTF_THUMB_ARCH_VERSION 4 /* RVCT sets __TARGET_ARCH_THUMB */ @@ -385,6 +387,11 @@ #define WTF_OS_HURD 1 #endif +/* OS(INTEGRITY) - INTEGRITY */ +#ifdef __INTEGRITY +#define WTF_OS_INTEGRITY 1 +#endif + /* OS(LINUX) - Linux */ #ifdef __linux__ #define WTF_OS_LINUX 1 @@ -433,6 +440,7 @@ || OS(DARWIN) \ || OS(FREEBSD) \ || OS(HURD) \ + || OS(INTEGRITY) \ || OS(LINUX) \ || OS(NETBSD) \ || OS(OPENBSD) \ @@ -603,7 +611,9 @@ #if OS(UNIX) #define HAVE_ERRNO_H 1 -#define HAVE_MMAP 1 +#if !OS(INTEGRITY) +#define HAVE_MMAP 1 +#endif #define HAVE_SIGNAL_H 1 #define HAVE_STRINGS_H 1 #define HAVE_SYS_PARAM_H 1 -- cgit v1.2.3 From 6e568c6ef5b34e32b0e2ec7b66d01d63888166a5 Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Fri, 13 Jan 2017 18:31:13 +0900 Subject: Fix build without feature.im Change-Id: I9c0c0138e48b30a443307faf6cd7251017bf84ae Reviewed-by: Lars Knoll --- src/quick/items/qquicktextedit.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index b99e53b6c8..94da44c00d 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -1729,7 +1729,9 @@ void QQuickTextEdit::select(int start, int end) // QTBUG-11100 updateSelection(); +#if QT_CONFIG(im) updateInputMethod(); +#endif } /*! -- cgit v1.2.3 From 0e3380f9c6ab6e3ea7398caccf5aa84f1575f1cd Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 13 Jan 2017 13:31:35 +0100 Subject: Fix crash when C++ QJSValue parameterized signal interacts with JS When converting the parameters of a C++ signal to JS values to provide to a signal handler written in JS, the conversion of a QJSValue to a QV4::Value* may yield a null pointer in case of a default constructed QJSValue for example. This is a regression from commit aa869cbb06bcf005e238059a2cb0205947ff0b5f and we must check for this. Task-number: QTBUG-58133 Change-Id: I528b606b2851dfb3072e54902bd8843d31571a55 Reviewed-by: Lars Knoll --- src/qml/qml/qqmlboundsignal.cpp | 5 ++++- tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml | 2 ++ tests/auto/qml/qqmlecmascript/testtypes.h | 1 + tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index c4af82133a..d207a4908c 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -199,7 +199,10 @@ void QQmlBoundSignalExpression::evaluate(void **a) // for several cases (such as QVariant type and QObject-derived types) //args[ii] = engine->metaTypeToJS(type, a[ii + 1]); if (type == qMetaTypeId()) { - callData->args[ii] = *QJSValuePrivate::getValue(reinterpret_cast(a[ii + 1])); + if (QV4::Value *v4Value = QJSValuePrivate::getValue(reinterpret_cast(a[ii + 1]))) + callData->args[ii] = *v4Value; + else + callData->args[ii] = QV4::Encode::undefined(); } else if (type == QMetaType::QVariant) { callData->args[ii] = scope.engine->fromVariant(*((QVariant *)a[ii + 1])); } else if (type == QMetaType::Int) { diff --git a/tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml b/tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml index 4fc2dab943..676593096c 100644 --- a/tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml +++ b/tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml @@ -15,4 +15,6 @@ MyQmlObject onMySignal: { intProperty = a; realProperty = b; colorProperty = c; variantProperty = d; enumProperty = e; qtEnumProperty = f; } onBasicSignal: root.mySignal(10, 19.2, Qt.rgba(1, 1, 0, 1), Qt.rgba(1, 0, 1, 1), MyQmlObject.EnumValue3, Qt.LeftButton) + + onQjsValueEmittingSignal: {} } diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h index 47fb2a56e7..1f7f3344ef 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.h +++ b/tests/auto/qml/qqmlecmascript/testtypes.h @@ -244,6 +244,7 @@ signals: void signalWithGlobalName(int parseInt); void intChanged(); void qjsvalueChanged(); + void qjsValueEmittingSignal(QJSValue value); public slots: void deleteMe() { delete this; } diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 88a8886ecb..b8f12e772d 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -1410,6 +1410,7 @@ void tst_qqmlecmascript::signalParameterTypes() QVERIFY(object != 0); emit object->basicSignal(); + emit object->qjsValueEmittingSignal(QJSValue()); QCOMPARE(object->property("intProperty").toInt(), 10); QCOMPARE(object->property("realProperty").toReal(), 19.2); -- cgit v1.2.3 From 5f828705bd694e71f6971f9e441cd6107ecb8130 Mon Sep 17 00:00:00 2001 From: Kavindra Palaraja Date: Fri, 6 Jan 2017 23:29:43 +0100 Subject: Remove documentation references to internal functions QSGOpacityNode::combinedOpacity() and QSGTransformNode::combinedMatrix() are intended to be internal. Task-number: QTBUG-53897 Change-Id: Icc73476eb8af5cdc673f7ce9bacd25ecc75202b5 Reviewed-by: Robin Burchell Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/coreapi/qsgnode.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/quick/scenegraph/coreapi/qsgnode.cpp b/src/quick/scenegraph/coreapi/qsgnode.cpp index a1e1ef8c27..7ef75d4b4c 100644 --- a/src/quick/scenegraph/coreapi/qsgnode.cpp +++ b/src/quick/scenegraph/coreapi/qsgnode.cpp @@ -337,13 +337,6 @@ QSGNode::~QSGNode() to the scene graph and will cause the preprocess() function to be called for every frame the node is rendered. - The preprocess function is called before the update pass that propagates - opacity and transformations through the scene graph. That means that - functions like QSGOpacityNode::combinedOpacity() and - QSGTransformNode::combinedMatrix() will not contain up-to-date values. - If such values are changed during the preprocess, these changes will be - propagated through the scene graph before it is rendered. - \warning Beware of deleting nodes while they are being preprocessed. It is possible, with a small performance hit, to delete a single node during its own preprocess call. Deleting a subtree which has nodes that also use -- cgit v1.2.3 From e85ebe01b61a64ed64592dedb71c5913cd5080fd Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Thu, 12 Jan 2017 21:36:38 +0100 Subject: Blacklist imageSource and svg tests QtSvg changed how the dimensions of an SVG are determined in 4bd5d6ced07d2d0e643a13e7cebb228c521d2046. These tests assume the old behavior at present, so blacklist the tests so qt5 integration can proceed. Task-number: QTBUG-58082 Change-Id: Ia579fbe6736932c081f9873d84bea4c01a975bad Reviewed-by: Lars Schmertmann Reviewed-by: Liang Qi Reviewed-by: Shawn Rutledge --- tests/auto/quick/qquickimage/BLACKLIST | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 tests/auto/quick/qquickimage/BLACKLIST diff --git a/tests/auto/quick/qquickimage/BLACKLIST b/tests/auto/quick/qquickimage/BLACKLIST new file mode 100644 index 0000000000..c081228f5e --- /dev/null +++ b/tests/auto/quick/qquickimage/BLACKLIST @@ -0,0 +1,6 @@ +#QTBUG-58082 +[svg] +* +#QTBUG-58082 +[imageSource] +* -- cgit v1.2.3 From efa22507386d3a0dcc97b703219dcf9714f55a8d Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Fri, 13 Jan 2017 08:40:29 +0100 Subject: Deprecate Text::doLayout() in favor of forceLayout() Item views and positioners all have now forceLayout(), so make the Text element API consistent with them. The old doLayout(), which sounds more like an internal helper method, is deprecated and marked for removal in Qt 6. [ChangeLog][QtQuick][Text] Deprecated doLayout() in favor of forceLayout(). Change-Id: I051988fca13c4cd84904f7b268d51f6a96f28af3 Reviewed-by: Robin Burchell --- src/quick/items/qquickitemsmodule.cpp | 1 + src/quick/items/qquicktext.cpp | 14 +++++++++++++- src/quick/items/qquicktext_p.h | 3 ++- tests/testapplications/textlayout/styledtext-layout.qml | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 5bba52ed73..a8824de9c8 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -376,6 +376,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType(uri, 2, 9, "Flickable"); qmlRegisterType(uri, 2, 9, "MouseArea"); + qmlRegisterType(uri, 2, 9, "Text"); qmlRegisterType(uri, 2, 9, "TextInput"); qmlRegisterType(uri, 2, 9, "TouchPoint"); qRegisterMetaType("QPointingDeviceUniqueId"); diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index 30e9c71143..965fb0102f 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -2795,10 +2795,22 @@ void QQuickText::setRenderType(QQuickText::RenderType renderType) /*! \qmlmethod QtQuick::Text::doLayout() + \deprecated - Triggers a re-layout of the displayed text. + Use \l forceLayout() instead. */ void QQuickText::doLayout() +{ + forceLayout(); +} + +/*! + \qmlmethod QtQuick::Text::forceLayout() + \since 5.9 + + Triggers a re-layout of the displayed text. +*/ +void QQuickText::forceLayout() { Q_D(QQuickText); d->updateSize(); diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h index 40dbd51f39..c3d3906e7e 100644 --- a/src/quick/items/qquicktext_p.h +++ b/src/quick/items/qquicktext_p.h @@ -218,7 +218,8 @@ public: QRectF boundingRect() const Q_DECL_OVERRIDE; QRectF clipRect() const Q_DECL_OVERRIDE; - Q_INVOKABLE void doLayout(); + Q_INVOKABLE void doLayout(); // ### Qt 6: remove + Q_REVISION(9) Q_INVOKABLE void forceLayout(); RenderType renderType() const; void setRenderType(RenderType renderType); diff --git a/tests/testapplications/textlayout/styledtext-layout.qml b/tests/testapplications/textlayout/styledtext-layout.qml index 4ad0c7e279..80f62a6b8f 100644 --- a/tests/testapplications/textlayout/styledtext-layout.qml +++ b/tests/testapplications/textlayout/styledtext-layout.qml @@ -88,7 +88,7 @@ Rectangle { drag.target: rect acceptedButtons: Qt.LeftButton | Qt.RightButton onClicked: mouse.button == Qt.RightButton ? myText.font.pixelSize -= 1 : myText.font.pixelSize += 1 - onPositionChanged: myText.doLayout() + onPositionChanged: myText.forceLayout() } } } -- cgit v1.2.3 From db462cce86dba0be80239d4aaaea668ef173af3d Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Fri, 13 Jan 2017 09:41:38 +0100 Subject: QQuickItemViewPrivate: cleanup superfluous semi-colons Change-Id: I178a9630353346f85dd67cfb552dde8ad4ca350e Reviewed-by: Robin Burchell --- src/quick/items/qquickitemview_p_p.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h index a8e66301c1..4ebb632840 100644 --- a/src/quick/items/qquickitemview_p_p.h +++ b/src/quick/items/qquickitemview_p_p.h @@ -348,8 +348,8 @@ protected: virtual bool showFooterForIndex(int index) const = 0; virtual void updateHeader() = 0; virtual void updateFooter() = 0; - virtual bool hasStickyHeader() const { return false; }; - virtual bool hasStickyFooter() const { return false; }; + virtual bool hasStickyHeader() const { return false; } + virtual bool hasStickyFooter() const { return false; } virtual void createHighlight() = 0; virtual void updateHighlight() = 0; -- cgit v1.2.3 From ec5f3fa6b7ddf0ed80801f70add90444f3714593 Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Fri, 13 Jan 2017 17:41:34 +0900 Subject: Fix build without feature.shortcut Change-Id: Id0ea0037db4cc3878ae2f75109aa3a7daa120189 Reviewed-by: Lars Knoll --- src/quick/items/qquickevents_p_p.h | 2 ++ src/quick/util/qquickutilmodule.cpp | 9 ++++++++- src/quick/util/util.pri | 9 +++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h index 7b281623fe..cf6f83e5b1 100644 --- a/src/quick/items/qquickevents_p_p.h +++ b/src/quick/items/qquickevents_p_p.h @@ -108,7 +108,9 @@ public: bool isAccepted() { return event.isAccepted(); } void setAccepted(bool accepted) { event.setAccepted(accepted); } +#if QT_CONFIG(shortcut) Q_REVISION(2) Q_INVOKABLE bool matches(QKeySequence::StandardKey key) const { return event.matches(key); } +#endif private: QKeyEvent event; diff --git a/src/quick/util/qquickutilmodule.cpp b/src/quick/util/qquickutilmodule.cpp index c1bc3d60b8..5728ad608e 100644 --- a/src/quick/util/qquickutilmodule.cpp +++ b/src/quick/util/qquickutilmodule.cpp @@ -54,7 +54,9 @@ #include "qquicktextmetrics_p.h" #include "qquicktransition_p.h" #include "qquickanimator_p.h" +#if QT_CONFIG(shortcut) #include "qquickshortcut_p.h" +#endif #include "qquickvalidator_p.h" #include #include @@ -63,7 +65,9 @@ #include #include +#if QT_CONFIG(shortcut) Q_DECLARE_METATYPE(QKeySequence::StandardKey) +#endif void QQuickUtilModule::defineModule() { @@ -114,13 +118,16 @@ void QQuickUtilModule::defineModule() qmlRegisterCustomType("QtQuick",2,0,"PropertyChanges", new QQuickPropertyChangesParser); +#if QT_CONFIG(shortcut) qRegisterMetaType(); qmlRegisterUncreatableType("QtQuick", 2, 2, "StandardKey", QStringLiteral("Cannot create an instance of StandardKey.")); +#endif qmlRegisterType("QtQuick", 2, 4, "FontMetrics"); qmlRegisterType("QtQuick", 2, 4, "TextMetrics"); +#if QT_CONFIG(shortcut) qmlRegisterType("QtQuick", 2, 5, "Shortcut"); - qmlRegisterType("QtQuick", 2, 6, "Shortcut"); +#endif } diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri index 1ef1018a31..b53b132cce 100644 --- a/src/quick/util/util.pri +++ b/src/quick/util/util.pri @@ -26,7 +26,6 @@ SOURCES += \ $$PWD/qquickanimatorcontroller.cpp \ $$PWD/qquickfontmetrics.cpp \ $$PWD/qquicktextmetrics.cpp \ - $$PWD/qquickshortcut.cpp \ $$PWD/qquickvalidator.cpp !contains(QT_CONFIG, no-qml-debug): SOURCES += $$PWD/qquickprofiler.cpp @@ -63,9 +62,15 @@ HEADERS += \ $$PWD/qquickprofiler_p.h \ $$PWD/qquickfontmetrics_p.h \ $$PWD/qquicktextmetrics_p.h \ - $$PWD/qquickshortcut_p.h \ $$PWD/qquickvalidator_p.h +qtConfig(shortcut) { + SOURCES += \ + $$PWD/qquickshortcut.cpp + HEADERS += \ + $$PWD/qquickshortcut_p.h +} + qtConfig(quick-path) { SOURCES += \ $$PWD/qquickpath.cpp \ -- cgit v1.2.3 From ed024294c570b948970b36bc8ad8b303bfeebe4a Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Thu, 12 Jan 2017 21:42:57 +0100 Subject: Fix imageSource and svg tests after change to how QtSvg interprets image size These tests were blacklisted after QtSvg/4bd5d6ced07d2d0e643a13e7cebb228c521d2046. in order to integrate qt5.git. Now, fix the tests to match the new behavior, and remove the blacklisting. Task-number: QTBUG-58082 Change-Id: I77abe995095ee52978c5957e49e1547b3af7708b Reviewed-by: Lars Schmertmann Reviewed-by: Shawn Rutledge --- tests/auto/quick/qquickimage/BLACKLIST | 6 ------ tests/auto/quick/qquickimage/tst_qquickimage.cpp | 12 ++++++------ 2 files changed, 6 insertions(+), 12 deletions(-) delete mode 100644 tests/auto/quick/qquickimage/BLACKLIST diff --git a/tests/auto/quick/qquickimage/BLACKLIST b/tests/auto/quick/qquickimage/BLACKLIST deleted file mode 100644 index c081228f5e..0000000000 --- a/tests/auto/quick/qquickimage/BLACKLIST +++ /dev/null @@ -1,6 +0,0 @@ -#QTBUG-58082 -[svg] -* -#QTBUG-58082 -[imageSource] -* diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp index d345163db5..0b48c34b92 100644 --- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp +++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp @@ -145,9 +145,9 @@ void tst_qquickimage::imageSource_data() QTest::newRow("remote") << "/colors.png" << 120.0 << 120.0 << true << false << true << ""; QTest::newRow("remote redirected") << "/oldcolors.png" << 120.0 << 120.0 << true << false << false << ""; if (QImageReader::supportedImageFormats().contains("svg")) - QTest::newRow("remote svg") << "/heart.svg" << 550.0 << 500.0 << true << false << false << ""; + QTest::newRow("remote svg") << "/heart.svg" << 595.0 << 841.0 << true << false << false << ""; if (QImageReader::supportedImageFormats().contains("svgz")) - QTest::newRow("remote svgz") << "/heart.svgz" << 550.0 << 500.0 << true << false << false << ""; + QTest::newRow("remote svgz") << "/heart.svgz" << 595.0 << 841.0 << true << false << false << ""; QTest::newRow("remote not found") << "/no-such-file.png" << 0.0 << 0.0 << true << false << true << ":2:1: QML Image: Error transferring {{ServerBaseUrl}}/no-such-file.png - server replied: Not found"; @@ -402,12 +402,12 @@ void tst_qquickimage::svg() component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QQuickImage *obj = qobject_cast(component.create()); QVERIFY(obj != 0); - QCOMPARE(obj->width(), 300.0); - QCOMPARE(obj->height(), 273.0); + QCOMPARE(obj->width(), 212.0); + QCOMPARE(obj->height(), 300.0); obj->setSourceSize(QSize(200,200)); - QCOMPARE(obj->width(), 200.0); - QCOMPARE(obj->height(), 182.0); + QCOMPARE(obj->width(), 141.0); + QCOMPARE(obj->height(), 200.0); delete obj; } -- cgit v1.2.3 From 04f91c0505495ae15d29c84b570a1f8a2a9347cb Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Sat, 14 Jan 2017 13:09:00 +0900 Subject: Fix build without feature.statemachine Change-Id: Iea95465a88627e312259ea62a8908d9cbb3f82ac Reviewed-by: Lars Knoll --- src/imports/imports.pro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/imports/imports.pro b/src/imports/imports.pro index cad02a2980..c49c05956d 100644 --- a/src/imports/imports.pro +++ b/src/imports/imports.pro @@ -5,10 +5,10 @@ SUBDIRS += \ qtqml \ folderlistmodel \ localstorage \ - models \ - statemachine + models qtConfig(settings): SUBDIRS += settings +qtConfig(statemachine): SUBDIRS += statemachine qtHaveModule(quick) { SUBDIRS += \ -- cgit v1.2.3 From 563b640de4312d4a06f33c4db24bd2444586889f Mon Sep 17 00:00:00 2001 From: Kavindra Palaraja Date: Sun, 15 Jan 2017 10:31:07 +0100 Subject: Clarify that QML's date object includes time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-42495 Change-Id: I0f7693ed32d3ec696f5c75b7ce7acdb41dd0ce6f Reviewed-by: Topi Reiniö --- src/qml/doc/src/qmltypereference.qdoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qml/doc/src/qmltypereference.qdoc b/src/qml/doc/src/qmltypereference.qdoc index f32574fcc1..b2bb9ebd18 100644 --- a/src/qml/doc/src/qmltypereference.qdoc +++ b/src/qml/doc/src/qmltypereference.qdoc @@ -89,7 +89,7 @@ provided: \ingroup qtquickbasictypes \brief a date value. -The \c date type refers to a date value. +The \c date type refers to a date value, including the time of the day. To create a \c date value, specify it as a "YYYY-MM-DD" string: @@ -100,7 +100,7 @@ MyDatePicker { minDate: "2000-01-01"; maxDate: "2020-12-31" } To read a date value returned from a C++ extension class, use \l{QtQml::Qt::formatDate()}{Qt.formatDate()} and \l{QtQml::Qt::formatDateTime()}{Qt.formatDateTime()}. -When integrating with C++, note that any QDate value +When integrating with C++, note that any QDate or QDateTime value \l{qtqml-cppintegration-data.html}{passed into QML from C++} is automatically converted into a \c date value, and vice-versa. -- cgit v1.2.3 From d8ce18b323f0eb8850177f86065f520bb555b5a4 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 16 Jan 2017 10:36:45 +0100 Subject: Quick: Remove last foreach, and mark QT_NO_FOREACH Longer term, we should QT_NO_FOREACH .qmake.conf, but a number of other parts of the codebase still use foreach. Change-Id: I105cdbe2a64ae40ffa53d3aaa8765b09195af841 Reviewed-by: Simon Hausmann --- src/quick/items/qquickitem.cpp | 2 +- src/quick/quick.pro | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 01737548c8..f7b9a58329 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -8389,7 +8389,7 @@ void QQuickItemWrapper::markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine { QObjectWrapper::Data *This = static_cast(that); if (QQuickItem *item = static_cast(This->object())) { - foreach (QQuickItem *child, QQuickItemPrivate::get(item)->childItems) + for (QQuickItem *child : qAsConst(QQuickItemPrivate::get(item)->childItems)) QV4::QObjectWrapper::markWrapper(child, e); } QV4::QObjectWrapper::markObjects(that, e); diff --git a/src/quick/quick.pro b/src/quick/quick.pro index 8f4f9a8290..eae9b09b2f 100644 --- a/src/quick/quick.pro +++ b/src/quick/quick.pro @@ -9,6 +9,8 @@ win32-msvc*:DEFINES *= _CRT_SECURE_NO_WARNINGS solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2 win32:!winrt: LIBS += -luser32 +DEFINES += QT_NO_FOREACH + exists("qqml_enable_gcov") { QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage -fno-elide-constructors LIBS_PRIVATE += -lgcov -- cgit v1.2.3 From 01f7a9dbe2e41434db34841f7d0c812e7a492128 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Sun, 15 Jan 2017 15:25:25 +0100 Subject: QQmlApplicationEngine: Yet another fix after QUrl behavior changes in QtBase Picture the following application: QQmlApplication qAppEngine("main.qml"); With main.qml: ... AComponentInTheSameDirectory { } ... This was failing, with the error: file:main.qml:13 AComponentInTheSameDirectory is not a type Which is wrong, but also reveals the root cause in that the original filename was not a fully resolved path. Change-Id: Ifc5557cc43f4bb92fd121ea9f7a37f09b3b38a9b Reviewed-by: David Faure --- src/qml/qml/qqmlapplicationengine.cpp | 15 +++++++++----- .../qqmlapplicationengine/data/LocalComponent.qml | 6 ++++++ .../data/nonResolvedLocal.qml | 9 ++++++++ .../tst_qqmlapplicationengine.cpp | 24 ++++++++++++++++++++++ 4 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 tests/auto/qml/qqmlapplicationengine/data/LocalComponent.qml create mode 100644 tests/auto/qml/qqmlapplicationengine/data/nonResolvedLocal.qml diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp index 8a97b7eba7..2a96d96302 100644 --- a/src/qml/qml/qqmlapplicationengine.cpp +++ b/src/qml/qml/qqmlapplicationengine.cpp @@ -190,9 +190,14 @@ void QQmlApplicationEnginePrivate::_q_finishLoad(QObject *o) /*! \fn QQmlApplicationEngine::objectCreated(QObject *object, const QUrl &url) - This signal is emitted when an object finishes loading. If loading was successful, \a object contains a pointer to the loaded object. - Otherwise the pointer is NULL. The \a url loaded is also provided, note that if a QString file path was initially passed to the - QQmlApplicationEngine, this url will be the equivalent of QUrl::fromLocalFile(filePath). + This signal is emitted when an object finishes loading. If loading was + successful, \a object contains a pointer to the loaded object, otherwise + the pointer is NULL. + + The \a url to the component the \a object came from is also provided. + + \note If the path to the component was provided as a QString containing a + relative path, the \a url will contain a fully resolved path to the file. */ /*! @@ -226,7 +231,7 @@ QQmlApplicationEngine::QQmlApplicationEngine(const QUrl &url, QObject *parent) This is provided as a convenience, and is the same as using the empty constructor and calling load afterwards. */ QQmlApplicationEngine::QQmlApplicationEngine(const QString &filePath, QObject *parent) - : QQmlApplicationEngine(QUrl::fromLocalFile(filePath), parent) + : QQmlApplicationEngine(QUrl::fromUserInput(filePath, QLatin1String("."), QUrl::AssumeLocalFile), parent) { } @@ -265,7 +270,7 @@ void QQmlApplicationEngine::load(const QUrl &url) void QQmlApplicationEngine::load(const QString &filePath) { Q_D(QQmlApplicationEngine); - d->startLoad(QUrl::fromLocalFile(filePath)); + d->startLoad(QUrl::fromUserInput(filePath, QLatin1String("."), QUrl::AssumeLocalFile)); } /*! diff --git a/tests/auto/qml/qqmlapplicationengine/data/LocalComponent.qml b/tests/auto/qml/qqmlapplicationengine/data/LocalComponent.qml new file mode 100644 index 0000000000..ece4f45b4a --- /dev/null +++ b/tests/auto/qml/qqmlapplicationengine/data/LocalComponent.qml @@ -0,0 +1,6 @@ +import QtQml 2.0 + +// used in nonResolvedLocal +QtObject { + +} diff --git a/tests/auto/qml/qqmlapplicationengine/data/nonResolvedLocal.qml b/tests/auto/qml/qqmlapplicationengine/data/nonResolvedLocal.qml new file mode 100644 index 0000000000..45a235346d --- /dev/null +++ b/tests/auto/qml/qqmlapplicationengine/data/nonResolvedLocal.qml @@ -0,0 +1,9 @@ +import QtQml 2.0 + +QtObject { + property bool success: true + + property QtObject local: LocalComponent { + } +} + diff --git a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp index 98b92e5fab..74add85cb0 100644 --- a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp +++ b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp @@ -42,6 +42,7 @@ public: private slots: void initTestCase(); void basicLoading(); + void testNonResolvedPath(); void application(); void applicationProperties(); private: @@ -83,6 +84,29 @@ void tst_qqmlapplicationengine::basicLoading() delete test; } +// make sure we resolve a relative URL to an absolute one, otherwise things +// will break. +void tst_qqmlapplicationengine::testNonResolvedPath() +{ + { + // NOTE NOTE NOTE! Missing testFileUrl is *WANTED* here! We want a + // non-resolved URL. + QQmlApplicationEngine test("data/nonResolvedLocal.qml"); + QCOMPARE(test.rootObjects().size(), 1); + QVERIFY(test.rootObjects()[0]); + QVERIFY(test.rootObjects()[0]->property("success").toBool()); + } + { + QQmlApplicationEngine test; + // NOTE NOTE NOTE! Missing testFileUrl is *WANTED* here! We want a + // non-resolved URL. + test.load("data/nonResolvedLocal.qml"); + QCOMPARE(test.rootObjects().size(), 1); + QVERIFY(test.rootObjects()[0]); + QVERIFY(test.rootObjects()[0]->property("success").toBool()); + } +} + void tst_qqmlapplicationengine::application() { /* This test batches together some tests about running an external application -- cgit v1.2.3 From 2c826af7c363e91656eb977fadb8afaf35f48290 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 16 Jan 2017 12:51:41 +0100 Subject: tests: Remove some vestigial references qtdeclarative hasn't relied on qtwebkit for a long time (since fbfb27a44a824fe479b526cbc6ccd4696d674c83 & 56d34a653a7ec4265835a7cb9b6352696f802e31 as early as 2011!). Change-Id: If02572617034bf2c3eecbf081b96b1ed0ad65b45 Reviewed-by: Simon Hausmann --- .../qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp | 42 ---------------------- tests/auto/quick/examples/tst_examples.cpp | 6 ---- 2 files changed, 48 deletions(-) diff --git a/tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp b/tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp index e16bfb08a2..3b982d1ab7 100644 --- a/tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp +++ b/tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp @@ -31,12 +31,6 @@ #include #include #include -/* -#include -#include -#include -#include -*/ #include #include #include @@ -150,42 +144,6 @@ void tst_qqmlsqldatabase::testQml_data() // test - in which case increment total_databases_created_by_tests above. } -/* -class QWebPageWithJavaScriptConsoleMessages : public QWebPage { -public: - void javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID) - { - qWarning() << sourceID << ":" << lineNumber << ":" << message; - } -}; - -void tst_qqmlsqldatabase::validateAgainstWebkit() -{ - // Validates tests against WebKit (HTML5) support. - // - QFETCH(QString, jsfile); - QFETCH(QString, result); - QFETCH(int, databases); - - QFile f(jsfile); - QVERIFY(f.open(QIODevice::ReadOnly)); - QString js=f.readAll(); - - QWebPageWithJavaScriptConsoleMessages webpage; - webpage.settings()->setOfflineStoragePath(dbDir()); - webpage.settings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, true); - - QEXPECT_FAIL("","WebKit doesn't support openDatabaseSync yet", Continue); - QCOMPARE(webpage.mainFrame()->evaluateJavaScript(js).toString(),result); - - QTest::qWait(100); // WebKit crashes if you quit it too fast - - QWebSecurityOrigin origin = webpage.mainFrame()->securityOrigin(); - QList dbs = origin.databases(); - QCOMPARE(dbs.count(), databases); -} -*/ - void tst_qqmlsqldatabase::testQml() { if (engine->offlineStoragePath().isEmpty()) diff --git a/tests/auto/quick/examples/tst_examples.cpp b/tests/auto/quick/examples/tst_examples.cpp index 1ca809c05f..d5c9aaeb90 100644 --- a/tests/auto/quick/examples/tst_examples.cpp +++ b/tests/auto/quick/examples/tst_examples.cpp @@ -88,12 +88,6 @@ tst_examples::tst_examples() excludedDirs << "snippets/qml/qtbinding"; excludedDirs << "snippets/qml/imports"; -#ifdef QT_NO_WEBKIT - excludedDirs << "qtquick/modelviews/webview"; - excludedDirs << "demos/webbrowser"; - excludedDirs << "doc/src/snippets/qml/webview"; -#endif - #ifdef QT_NO_XMLPATTERNS excludedDirs << "demos/twitter"; excludedDirs << "demos/flickr"; -- cgit v1.2.3 From 74da92163995ae181a9915d63a87b066628d604d Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 16 Jan 2017 12:55:01 +0100 Subject: networktransparency: Remove reference to WebView, and instead only use local examples Saves us from any future renaming or deprecation hassle. Change-Id: Ied7bec12bb53d4e5a6661c36873a14fc7d68711b Reviewed-by: Simon Hausmann --- src/qml/doc/src/qmllanguageref/documents/networktransparency.qdoc | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/qml/doc/src/qmllanguageref/documents/networktransparency.qdoc b/src/qml/doc/src/qmllanguageref/documents/networktransparency.qdoc index 7fa271c2d9..5cfd80f8a0 100644 --- a/src/qml/doc/src/qmllanguageref/documents/networktransparency.qdoc +++ b/src/qml/doc/src/qmllanguageref/documents/networktransparency.qdoc @@ -48,12 +48,8 @@ Image { } \endqml -Network transparency is supported throughout QML, for example: - -\list -\li Fonts - the \c source property of FontLoader is a URL -\li WebViews - the \c url property of WebView (obviously!) -\endlist +Network transparency is supported throughout QML, for example, both the FontLoader +and Image elements support loading resources from a remote server. Even QML types themselves can be on the network - if the \l {Prototyping with qmlscene} is used to load \tt http://example.com/mystuff/Hello.qml and that content refers to a type "World", the engine -- cgit v1.2.3 From 09dc5a0c4c08e8f13ddc81d82a9fc2d2af047165 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 16 Jan 2017 12:56:08 +0100 Subject: Remove QQuickWebView from QQmlEngine documentation It's not part of this module, and promising something against a module so distinct from qtdeclarative seems like a risky choice, even if the class was a public and supported one -- checking qtwebkit's source shows QQuickWebView is in a private header. Change-Id: Ib250542e5a78083cbabe55217b9b9192d3a863fb Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlengine.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 3a95d353f5..df7d2806b9 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -2149,8 +2149,7 @@ bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList Returns the directory where SQL and other offline storage is placed. - QQuickWebView and the SQL databases created with openDatabase() - are stored here. + The SQL databases created with openDatabase() are stored here. The default is QML/OfflineStorage in the platform-standard user application data directory. -- cgit v1.2.3 From 8eada7ae7d41a2d93142ea1a6454ab2bbb0998ed Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Fri, 30 Dec 2016 13:20:24 +0100 Subject: ListView: allow flicking to both directions Previously flicking was restricted to the orientation of the ListView. [ChangeLog][QtQuick][ListView] Made it possible to enable horizontal flicking in a vertical ListView, and vice versa. The only thing apps must do is to specify the desired flick direction and the content width (vertical ListView) or content height (horizontal ListView), which is not calculated by ListView. Change-Id: Ic370e57f5d18679940d48e7a2c20c200b2ef36d1 Task-number: QTBUG-52553 Task-number: QTBUG-56501 Reviewed-by: Robin Burchell Reviewed-by: Shawn Rutledge --- src/quick/doc/snippets/qml/listview/listview.qml | 15 ++++ src/quick/items/qquicklistview.cpp | 54 +++++++++++++-- src/quick/items/qquicklistview_p.h | 2 + .../qquicklistview/data/flickBothDirections.qml | 70 +++++++++++++++++++ .../quick/qquicklistview/tst_qquicklistview.cpp | 79 ++++++++++++++++++++++ 5 files changed, 214 insertions(+), 6 deletions(-) create mode 100644 tests/auto/quick/qquicklistview/data/flickBothDirections.qml diff --git a/src/quick/doc/snippets/qml/listview/listview.qml b/src/quick/doc/snippets/qml/listview/listview.qml index 31896626a4..ecb5fea076 100644 --- a/src/quick/doc/snippets/qml/listview/listview.qml +++ b/src/quick/doc/snippets/qml/listview/listview.qml @@ -146,4 +146,19 @@ ListView { } //![isCurrentItem] +//![flickBothDirections] +ListView { + width: 180; height: 200 + + contentWidth: 320 + flickableDirection: Flickable.AutoFlickDirection + + model: ContactModel {} + delegate: Row { + Text { text: 'Name: ' + name; width: 160 } + Text { text: 'Number: ' + number; width: 160 } + } +} +//![flickBothDirections] + } diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index f89a995e76..9419d3cf96 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -1462,9 +1462,15 @@ void QQuickListViewPrivate::fixupPosition() void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent) { - if ((orient == QQuickListView::Horizontal && &data == &vData) - || (orient == QQuickListView::Vertical && &data == &hData)) + if (orient == QQuickListView::Horizontal && &data == &vData) { + if (flickableDirection != QQuickFlickable::HorizontalFlick) + QQuickItemViewPrivate::fixup(data, minExtent, maxExtent); + return; + } else if (orient == QQuickListView::Vertical && &data == &hData) { + if (flickableDirection != QQuickFlickable::VerticalFlick) + QQuickItemViewPrivate::fixup(data, minExtent, maxExtent); return; + } correctFlick = false; fixupMode = moveReason == Mouse ? fixupMode : Immediate; @@ -1813,6 +1819,19 @@ bool QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte \image listview-layout-righttoleft.png \endtable + \section1 Flickable Direction + + By default, a vertical ListView sets \l {Flickable::}{flickableDirection} to \e Flickable.Vertical, + and a horizontal ListView sets it to \e Flickable.Horizontal. Furthermore, a vertical ListView only + calculates (estimates) the \l {Flickable::}{contentHeight}, and a horizontal ListView only calculates + the \l {Flickable::}{contentWidth}. The other dimension is set to \e -1. + + Since Qt 5.9 (Qt Quick 2.9), it is possible to make a ListView that can be flicked to both directions. + In order to do this, the \l {Flickable::}{flickableDirection} can be set to \e Flickable.AutoFlickDirection + or \e Flickable.AutoFlickIfNeeded, and the desired \e contentWidth or \e contentHeight must be provided. + + \snippet qml/listview/listview.qml flickBothDirections + \sa {QML Data Models}, GridView, PathView, {Qt Quick Examples - Views} */ QQuickListView::QQuickListView(QQuickItem *parent) @@ -2099,6 +2118,8 @@ void QQuickListView::setSpacing(qreal spacing) \li Vertical orientation: \image listview-highlight.png \endtable + + \sa {Flickable Direction} */ QQuickListView::Orientation QQuickListView::orientation() const { @@ -2112,12 +2133,18 @@ void QQuickListView::setOrientation(QQuickListView::Orientation orientation) if (d->orient != orientation) { d->orient = orientation; if (d->orient == Vertical) { - setContentWidth(-1); - setFlickableDirection(VerticalFlick); + if (d->flickableDirection == HorizontalFlick) { + setFlickableDirection(VerticalFlick); + if (isComponentComplete()) + setContentWidth(-1); + } setContentX(0); } else { - setContentHeight(-1); - setFlickableDirection(HorizontalFlick); + if (d->flickableDirection == VerticalFlick) { + setFlickableDirection(HorizontalFlick); + if (isComponentComplete()) + setContentHeight(-1); + } setContentY(0); } d->regenerate(true); @@ -3042,6 +3069,21 @@ void QQuickListView::initItem(int index, QObject *object) } } +qreal QQuickListView::maxYExtent() const +{ + Q_D(const QQuickListView); + if (d->layoutOrientation() == Qt::Horizontal && d->flickableDirection != HorizontalFlick) + return QQuickFlickable::maxYExtent(); + return QQuickItemView::maxYExtent(); +} + +qreal QQuickListView::maxXExtent() const +{ + Q_D(const QQuickListView); + if (d->layoutOrientation() == Qt::Vertical && d->flickableDirection != VerticalFlick) + return QQuickFlickable::maxXExtent(); + return QQuickItemView::maxXExtent(); +} /*! \qmlmethod QtQuick::ListView::incrementCurrentIndex() diff --git a/src/quick/items/qquicklistview_p.h b/src/quick/items/qquicklistview_p.h index 3a871e88e9..dbed8dfed4 100644 --- a/src/quick/items/qquicklistview_p.h +++ b/src/quick/items/qquicklistview_p.h @@ -196,6 +196,8 @@ protected: void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE; void geometryChanged(const QRectF &newGeometry,const QRectF &oldGeometry) Q_DECL_OVERRIDE; void initItem(int index, QObject *item) Q_DECL_OVERRIDE; + qreal maxYExtent() const Q_DECL_OVERRIDE; + qreal maxXExtent() const Q_DECL_OVERRIDE; }; class QQuickListViewAttached : public QQuickItemViewAttached diff --git a/tests/auto/quick/qquicklistview/data/flickBothDirections.qml b/tests/auto/quick/qquicklistview/data/flickBothDirections.qml new file mode 100644 index 0000000000..5d80ce4110 --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/flickBothDirections.qml @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.9 + +Rectangle { + width: 200 + height: 200 + ListView { + id: list + objectName: "list" + width: 100 + height: 100 + model: 20 + anchors.centerIn: parent + orientation: initialOrientation + contentWidth: initialContentWidth + contentHeight: initialContentHeight + flickableDirection: initialFlickableDirection + delegate: Rectangle { + width: list.orientation == ListView.Vertical ? 120 : 10 + height: list.orientation == ListView.Vertical ? 20 : 110 + color: Qt.rgba(0, 0, index / 19, 1) + opacity: 0.8 + } + Rectangle { + z: -1 + width: 100 + height: 100 + border.width: 1 + border.color: "red" + } + } +} diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index 4816d9c341..ff06c1e1a4 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -53,6 +53,7 @@ Q_DECLARE_METATYPE(Qt::LayoutDirection) Q_DECLARE_METATYPE(QQuickItemView::VerticalLayoutDirection) Q_DECLARE_METATYPE(QQuickItemView::PositionMode) Q_DECLARE_METATYPE(QQuickListView::Orientation) +Q_DECLARE_METATYPE(QQuickFlickable::FlickableDirection) Q_DECLARE_METATYPE(Qt::Key) using namespace QQuickViewTestUtil; @@ -205,6 +206,8 @@ private slots: void multipleDisplaced(); void flickBeyondBounds(); + void flickBothDirections(); + void flickBothDirections_data(); void destroyItemOnCreation(); void parentBinding(); @@ -7123,6 +7126,82 @@ void tst_QQuickListView::flickBeyondBounds() } } +void tst_QQuickListView::flickBothDirections() +{ + QFETCH(bool, initValues); + QFETCH(QQuickListView::Orientation, orientation); + QFETCH(QQuickFlickable::FlickableDirection, flickableDirection); + QFETCH(qreal, contentWidth); + QFETCH(qreal, contentHeight); + QFETCH(QPointF, targetPos); + + QQuickView *window = getView(); + QQuickViewTestUtil::moveMouseAway(window); + + QQmlContext *ctxt = window->rootContext(); + ctxt->setContextProperty("initialOrientation", initValues ? orientation : QQuickListView::Vertical); + ctxt->setContextProperty("initialFlickableDirection", initValues ? flickableDirection : QQuickFlickable::VerticalFlick); + ctxt->setContextProperty("initialContentWidth", initValues ? contentWidth : -1); + ctxt->setContextProperty("initialContentHeight", initValues ? contentHeight : -1); + + window->setSource(testFileUrl("flickBothDirections.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + QQuickListView *listview = findItem(window->rootObject(), "list"); + QVERIFY(listview); + + if (!initValues) { + listview->setOrientation(orientation); + listview->setFlickableDirection(flickableDirection); + if (contentWidth > 0) + listview->setContentWidth(contentWidth); + if (contentHeight > 0) + listview->setContentHeight(contentHeight); + } + + flick(window, QPoint(100, 100), QPoint(25, 25), 50); + QVERIFY(listview->isMoving()); + QTRY_VERIFY(!listview->isMoving()); + QCOMPARE(listview->contentX(), targetPos.x()); + QCOMPARE(listview->contentY(), targetPos.y()); +} + +void tst_QQuickListView::flickBothDirections_data() +{ + QTest::addColumn("initValues"); + QTest::addColumn("orientation"); + QTest::addColumn("flickableDirection"); + QTest::addColumn("contentWidth"); + QTest::addColumn("contentHeight"); + QTest::addColumn("targetPos"); + + // model: 20 + // listview: 100x100 + // vertical delegate: 120x20 -> contentHeight: 20x20=400 + // horizontal delegate: 10x110 -> contentWidth: 20x10=200 + + QTest::newRow("init:vertical,-1") << true << QQuickListView::Vertical << QQuickFlickable::VerticalFlick << -1. << -1. << QPointF(0, 300); + QTest::newRow("init:vertical,120") << true << QQuickListView::Vertical << QQuickFlickable::VerticalFlick<< 120. << -1. << QPointF(0, 300); + QTest::newRow("init:vertical,auto,-1") << true << QQuickListView::Vertical << QQuickFlickable::AutoFlickDirection << -1. << -1. << QPointF(0, 300); + QTest::newRow("init:vertical,auto,120") << true << QQuickListView::Vertical << QQuickFlickable::AutoFlickDirection << 120. << -1. << QPointF(20, 300); + + QTest::newRow("completed:vertical,-1") << false << QQuickListView::Vertical << QQuickFlickable::VerticalFlick << -1. << -1. << QPointF(0, 300); + QTest::newRow("completed:vertical,120") << false << QQuickListView::Vertical << QQuickFlickable::VerticalFlick << 120. << -1. << QPointF(0, 300); + QTest::newRow("completed:vertical,auto,-1") << false << QQuickListView::Vertical << QQuickListView::AutoFlickDirection << -1. << -1. << QPointF(0, 300); + QTest::newRow("completed:vertical,auto,120") << false << QQuickListView::Vertical << QQuickListView::AutoFlickDirection << 120. << -1. << QPointF(20, 300); + + QTest::newRow("init:horizontal,-1") << true << QQuickListView::Horizontal << QQuickFlickable::HorizontalFlick << -1. << -1. << QPointF(100, 0); + QTest::newRow("init:horizontal,110") << true << QQuickListView::Horizontal << QQuickFlickable::HorizontalFlick <<-1. << 110. << QPointF(100, 0); + QTest::newRow("init:horizontal,auto,-1") << true << QQuickListView::Horizontal << QQuickListView::AutoFlickDirection << -1. << -1. << QPointF(100, 0); + QTest::newRow("init:horizontal,auto,110") << true << QQuickListView::Horizontal << QQuickListView::AutoFlickDirection << -1. << 110. << QPointF(100, 10); + + QTest::newRow("completed:horizontal,-1") << false << QQuickListView::Horizontal << QQuickFlickable::HorizontalFlick << -1. << -1. << QPointF(100, 0); + QTest::newRow("completed:horizontal,110") << false << QQuickListView::Horizontal << QQuickFlickable::HorizontalFlick << -1. << 110. << QPointF(100, 0); + QTest::newRow("completed:horizontal,auto,-1") << false << QQuickListView::Horizontal << QQuickListView::AutoFlickDirection << -1. << -1. << QPointF(100, 0); + QTest::newRow("completed:horizontal,auto,110") << false << QQuickListView::Horizontal << QQuickListView::AutoFlickDirection << -1. << 110. << QPointF(100, 10); +} + void tst_QQuickListView::destroyItemOnCreation() { QaimModel model; -- cgit v1.2.3 From 0b82932dd3f6d0ef72a504b10beff8ea7a967a0d Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 16 Jan 2017 12:18:44 +0100 Subject: Item views: eliminate some repeated QList::at() access Change-Id: Iccc1ec0cf4408e25c04ca0be2562175e76d2d198 Reviewed-by: Robin Burchell --- src/quick/items/qquickgridview.cpp | 4 +++- src/quick/items/qquicklistview.cpp | 39 +++++++++++++++++++++++--------------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp index 14ea43f123..4359700362 100644 --- a/src/quick/items/qquickgridview.cpp +++ b/src/quick/items/qquickgridview.cpp @@ -2535,8 +2535,10 @@ void QQuickGridViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex countItemsRemoved -= removalResult.countChangeAfterVisibleItems; - for (int i=markerItemIndex+1; iposition() < viewEndPos; i++) { + for (int i=markerItemIndex+1; i(visibleItems.at(i)); + if (gridItem->position() >= viewEndPos) + break; if (!gridItem->transitionScheduledOrRunning()) { qreal origRowPos = gridItem->colPos(); qreal origColPos = gridItem->rowPos(); diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 9419d3cf96..5a39ff9422 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -438,11 +438,12 @@ qreal QQuickListViewPrivate::lastPosition() const int invisibleCount = INT_MIN; int delayRemovedCount = 0; for (int i = visibleItems.count()-1; i >= 0; --i) { - if (visibleItems.at(i)->index != -1) { + FxViewItem *item = visibleItems.at(i); + if (item->index != -1) { // Find the invisible count after the last visible item with known index - invisibleCount = model->count() - (visibleItems.at(i)->index + 1 + delayRemovedCount); + invisibleCount = model->count() - (item->index + 1 + delayRemovedCount); break; - } else if (visibleItems.at(i)->attached->delayRemove()) { + } else if (item->attached->delayRemove()) { ++delayRemovedCount; } } @@ -1172,12 +1173,12 @@ void QQuickListViewPrivate::updateSections() FxViewItem *item = visibleItems.at(i); QQuickListViewAttached *attached = static_cast(item->attached); attached->setPrevSection(prevSection); - if (visibleItems.at(i)->index != -1) { - QString propValue = model->stringValue(visibleItems.at(i)->index, sectionCriteria->property()); + if (item->index != -1) { + QString propValue = model->stringValue(item->index, sectionCriteria->property()); attached->setSection(sectionCriteria->sectionString(propValue)); - idx = visibleItems.at(i)->index; + idx = item->index; } - updateInlineSection(static_cast(visibleItems.at(i))); + updateInlineSection(static_cast(item)); if (prevAtt) prevAtt->setNextSection(sectionAt(prevIdx+1)); prevSection = attached->section(); @@ -1210,9 +1211,12 @@ void QQuickListViewPrivate::updateCurrentSection() qreal startPos = hasStickyHeader() ? header->endPosition() : viewPos; int index = 0; int modelIndex = visibleIndex; - while (index < visibleItems.count() && visibleItems.at(index)->endPosition() <= startPos) { - if (visibleItems.at(index)->index != -1) - modelIndex = visibleItems.at(index)->index; + while (index < visibleItems.count()) { + FxViewItem *item = visibleItems.at(index); + if (item->endPosition() > startPos) + break; + if (item->index != -1) + modelIndex = item->index; ++index; } @@ -1236,10 +1240,13 @@ void QQuickListViewPrivate::updateCurrentSection() qreal endPos = hasStickyFooter() ? footer->position() : viewPos + size(); if (nextSectionItem && !inlineSections) endPos -= orient == QQuickListView::Vertical ? nextSectionItem->height() : nextSectionItem->width(); - while (index < visibleItems.count() && static_cast(visibleItems.at(index))->itemPosition() < endPos) { - if (visibleItems.at(index)->index != -1) - modelIndex = visibleItems.at(index)->index; - lastSection = visibleItems.at(index)->attached->section(); + while (index < visibleItems.count()) { + FxListItemSG *listItem = static_cast(visibleItems.at(index)); + if (listItem->itemPosition() >= endPos) + break; + if (listItem->index != -1) + modelIndex = listItem->index; + lastSection = listItem->attached->section(); ++index; } @@ -3323,8 +3330,10 @@ void QQuickListViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex qreal sizeRemoved = -removalResult.sizeChangesAfterVisiblePos - (removalResult.countChangeAfterVisibleItems * (averageSize + spacing)); - for (int i=markerItemIndex+1; iposition() < viewEndPos; i++) { + for (int i=markerItemIndex+1; i(visibleItems.at(i)); + if (listItem->position() >= viewEndPos) + break; if (!listItem->transitionScheduledOrRunning()) { qreal pos = listItem->position(); listItem->setPosition(pos - sizeRemoved); -- cgit v1.2.3 From b54690c690b4e457c8c225db1822aa97ae48f021 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Thu, 12 Jan 2017 14:33:50 +0100 Subject: QQuickLayout: Use qmlWarning instead of qWarning to give context information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ie16508d22554c9b6dcd66adf6a59f32117edf1e3 Reviewed-by: Jan Arve Sæther --- src/imports/layouts/qquicklayout.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/imports/layouts/qquicklayout.cpp b/src/imports/layouts/qquicklayout.cpp index fd2ff4a73e..55ee3b63c6 100644 --- a/src/imports/layouts/qquicklayout.cpp +++ b/src/imports/layouts/qquicklayout.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include /*! @@ -678,7 +679,7 @@ QQuickLayout *QQuickLayoutAttached::parentLayout() const parentItem = parentItem->parentItem(); return qobject_cast(parentItem); } else { - qWarning("Layout must be attached to Item elements"); + qmlWarning(parent()) << "Layout must be attached to Item elements"; } return 0; } -- cgit v1.2.3 From 930385acd8d30a6e0d818806ab893fdce975385f Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Thu, 12 Jan 2017 15:01:33 +0100 Subject: QQuickGridLayout: Remove dead code in layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The attached isRowSet and isColumnSet check for values >= 0, and row/column getters also enforce a minimum return value of 0, so it is impossible for us to get a negative value for row/column if either of these is set -- and we can simply call the getter and rely on it to return 0 in the unset case. Change-Id: Iec80e7d7cf3738cf0a81e90b027ffe41e0f57369 Reviewed-by: Jan Arve Sæther --- src/imports/layouts/qquicklinearlayout.cpp | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/imports/layouts/qquicklinearlayout.cpp b/src/imports/layouts/qquicklinearlayout.cpp index 50b3eed87e..40aa8818a6 100644 --- a/src/imports/layouts/qquicklinearlayout.cpp +++ b/src/imports/layouts/qquicklinearlayout.cpp @@ -664,25 +664,14 @@ void QQuickGridLayout::insertLayoutItems() int &columnSpan = span[0]; int &rowSpan = span[1]; - bool invalidRowColumn = false; if (info) { if (info->isRowSet() || info->isColumnSet()) { // If row is specified and column is not specified (or vice versa), // the unspecified component of the cell position should default to 0 - row = column = 0; - if (info->isRowSet()) { - row = info->row(); - invalidRowColumn = row < 0; - } - if (info->isColumnSet()) { - column = info->column(); - invalidRowColumn = column < 0; - } - } - if (invalidRowColumn) { - qWarning("QQuickGridLayoutBase::insertLayoutItems: invalid row/column: %d", - row < 0 ? row : column); - return; + // The getters do this for us, as they will return 0 for an + // unset (or negative) value. + row = info->row(); + column = info->column(); } rowSpan = info->rowSpan(); columnSpan = info->columnSpan(); -- cgit v1.2.3 From 8990cc9e260ba1685cad23a68ba2ee672ea68a0f Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Thu, 12 Jan 2017 15:10:03 +0100 Subject: QQuickGridLayout: Use qmlWarning to give extra context to warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now have file & line number information pointing us to the location of the faulty child. Also take the effort to split the message into two, so it's clear which property is faulty (and which the value is representing). Change-Id: I8e515feeaf8fa1decf8aaf7adf0a02cce7aec0ea Reviewed-by: Jan Arve Sæther --- src/imports/layouts/qquicklinearlayout.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/imports/layouts/qquicklinearlayout.cpp b/src/imports/layouts/qquicklinearlayout.cpp index 40aa8818a6..887b9b1fa1 100644 --- a/src/imports/layouts/qquicklinearlayout.cpp +++ b/src/imports/layouts/qquicklinearlayout.cpp @@ -41,6 +41,7 @@ #include "qquickgridlayoutengine_p.h" #include "qquicklayoutstyleinfo_p.h" #include +#include #include "qdebug.h" #include @@ -675,12 +676,14 @@ void QQuickGridLayout::insertLayoutItems() } rowSpan = info->rowSpan(); columnSpan = info->columnSpan(); - if (columnSpan < 1 || rowSpan < 1) { - qWarning("QQuickGridLayoutBase::addItem: invalid row span/column span: %d", - rowSpan < 1 ? rowSpan : columnSpan); + if (columnSpan < 1) { + qmlWarning(child) << "Layout: invalid column span: " << columnSpan; return; - } + } else if (rowSpan < 1) { + qmlWarning(child) << "Layout: invalid row span: " << rowSpan; + return; + } alignment = info->alignment(); } -- cgit v1.2.3 From 373cdc297f343932218782d3587b98af5f8ccc53 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 16 Jan 2017 15:51:58 +0100 Subject: Remove remnants of blackberry platform support The last remnants were removed from qtbase in 5.7 making this all dead code, so match here too. Change-Id: I10f3f1c614562f2a97ade7cdf5002065d6f79e07 Reviewed-by: Simon Hausmann --- .../samegame/content/+blackberry/Settings.qml | 47 ----------------- .../quick/demos/samegame/content/BBSettings.qml | 61 ---------------------- examples/quick/demos/samegame/content/qmldir | 1 - examples/quick/demos/samegame/samegame.qrc | 2 - src/imports/layouts/qquicklayoutstyleinfo.cpp | 2 +- src/particles/qquickimageparticle.cpp | 16 ------ src/particles/shaders/imageparticle.vert | 6 +-- src/particles/shaders/imageparticle_core.vert | 6 +-- src/qml/qml/qqmlengine.cpp | 1 - src/qml/qml/qqmlplatform.cpp | 2 - src/quick/items/qquickflickablebehavior_p.h | 12 +---- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 2 +- tests/auto/quick/qquickimage/tst_qquickimage.cpp | 4 -- .../quick/qquickitemlayer/tst_qquickitemlayer.cpp | 4 -- tests/auto/quick/qquicktext/tst_qquicktext.cpp | 5 -- 15 files changed, 6 insertions(+), 165 deletions(-) delete mode 100644 examples/quick/demos/samegame/content/+blackberry/Settings.qml delete mode 100644 examples/quick/demos/samegame/content/BBSettings.qml diff --git a/examples/quick/demos/samegame/content/+blackberry/Settings.qml b/examples/quick/demos/samegame/content/+blackberry/Settings.qml deleted file mode 100644 index c744ca6f51..0000000000 --- a/examples/quick/demos/samegame/content/+blackberry/Settings.qml +++ /dev/null @@ -1,47 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 BlackBerry Limited. All rights reserved. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -pragma Singleton -import QtQml 2.0 - -// Instantiating a BBSettings class that can be easily tweaked for future -// BB devices (we may have more selectors added) -BBSettings { -} diff --git a/examples/quick/demos/samegame/content/BBSettings.qml b/examples/quick/demos/samegame/content/BBSettings.qml deleted file mode 100644 index cd6be7dcf5..0000000000 --- a/examples/quick/demos/samegame/content/BBSettings.qml +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 BlackBerry Limited. All rights reserved. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQml 2.0 - -QtObject { - // This height/width is here for desktop testing, otherwise - // we could just use Screen.width/Screen.height. - property int screenHeight: 1280 - property int screenWidth: 768 - - property int menuDelay: 500 - - property int headerHeight: 70 - property int footerHeight: 100 - - property int fontPixelSize: 55 - - property int blockSize: 64 - - property int toolButtonHeight: 64 - - property int menuButtonSpacing: 15 -} diff --git a/examples/quick/demos/samegame/content/qmldir b/examples/quick/demos/samegame/content/qmldir index 727989d006..3b552ec1f1 100644 --- a/examples/quick/demos/samegame/content/qmldir +++ b/examples/quick/demos/samegame/content/qmldir @@ -1,5 +1,4 @@ singleton Settings 1.0 Settings.qml -BBSettings 1.0 BBSettings.qml Block 1.0 Block.qml BlockEmitter 1.0 BlockEmitter.qml Button 1.0 Button.qml diff --git a/examples/quick/demos/samegame/samegame.qrc b/examples/quick/demos/samegame/samegame.qrc index e51d3fae05..348ee109f9 100644 --- a/examples/quick/demos/samegame/samegame.qrc +++ b/examples/quick/demos/samegame/samegame.qrc @@ -3,8 +3,6 @@ samegame.qml content/qmldir content/Settings.qml - content/BBSettings.qml - content/+blackberry/Settings.qml content/gfx/text-p1-won.png content/gfx/background-puzzle.png content/gfx/background.png diff --git a/src/imports/layouts/qquicklayoutstyleinfo.cpp b/src/imports/layouts/qquicklayoutstyleinfo.cpp index c33ceffb2d..5c8be8f306 100644 --- a/src/imports/layouts/qquicklayoutstyleinfo.cpp +++ b/src/imports/layouts/qquicklayoutstyleinfo.cpp @@ -50,7 +50,7 @@ QQuickLayoutStyleInfo::QQuickLayoutStyleInfo() qreal QQuickLayoutStyleInfo::spacing(Qt::Orientation /*orientation*/) const { -#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_BLACKBERRY) || defined(Q_OS_QNX) || defined(Q_OS_WINRT) +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_QNX) || defined(Q_OS_WINRT) // On Android and iOS the default spacing between each UI element is 8dp qreal spacing = 8.0; #else diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp index e82f17becd..ccfebddb0e 100644 --- a/src/particles/qquickimageparticle.cpp +++ b/src/particles/qquickimageparticle.cpp @@ -58,12 +58,6 @@ QT_BEGIN_NAMESPACE -#if defined(Q_OS_BLACKBERRY) -#define SHADER_PLATFORM_DEFINES "Q_OS_BLACKBERRY\n" -#else -#define SHADER_PLATFORM_DEFINES -#endif - //TODO: Make it larger on desktop? Requires fixing up shader code with the same define #define UNIFORM_ARRAY_SIZE 64 @@ -102,7 +96,6 @@ public: const bool isES = QOpenGLContext::currentContext()->isOpenGLES(); builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert")); - builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES)); builder.addDefinition(QByteArrayLiteral("TABLE")); builder.addDefinition(QByteArrayLiteral("DEFORM")); builder.addDefinition(QByteArrayLiteral("COLOR")); @@ -113,7 +106,6 @@ public: builder.clear(); builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag")); - builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES)); builder.addDefinition(QByteArrayLiteral("TABLE")); builder.addDefinition(QByteArrayLiteral("DEFORM")); builder.addDefinition(QByteArrayLiteral("COLOR")); @@ -180,7 +172,6 @@ public: const bool isES = QOpenGLContext::currentContext()->isOpenGLES(); builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert")); - builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES)); builder.addDefinition(QByteArrayLiteral("DEFORM")); builder.addDefinition(QByteArrayLiteral("COLOR")); if (isES) @@ -190,7 +181,6 @@ public: builder.clear(); builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag")); - builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES)); builder.addDefinition(QByteArrayLiteral("DEFORM")); builder.addDefinition(QByteArrayLiteral("COLOR")); if (isES) @@ -245,7 +235,6 @@ public: const bool isES = QOpenGLContext::currentContext()->isOpenGLES(); builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert")); - builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES)); builder.addDefinition(QByteArrayLiteral("SPRITE")); builder.addDefinition(QByteArrayLiteral("TABLE")); builder.addDefinition(QByteArrayLiteral("DEFORM")); @@ -257,7 +246,6 @@ public: builder.clear(); builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag")); - builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES)); builder.addDefinition(QByteArrayLiteral("SPRITE")); builder.addDefinition(QByteArrayLiteral("TABLE")); builder.addDefinition(QByteArrayLiteral("DEFORM")); @@ -327,7 +315,6 @@ public: const bool isES = QOpenGLContext::currentContext()->isOpenGLES(); builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert")); - builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES)); builder.addDefinition(QByteArrayLiteral("COLOR")); if (isES) builder.removeVersion(); @@ -336,7 +323,6 @@ public: builder.clear(); builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag")); - builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES)); builder.addDefinition(QByteArrayLiteral("COLOR")); if (isES) builder.removeVersion(); @@ -405,7 +391,6 @@ public: const bool isES = QOpenGLContext::currentContext()->isOpenGLES(); builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert")); - builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES)); if (isES) builder.removeVersion(); @@ -413,7 +398,6 @@ public: builder.clear(); builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag")); - builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES)); if (isES) builder.removeVersion(); diff --git a/src/particles/shaders/imageparticle.vert b/src/particles/shaders/imageparticle.vert index 377f831686..4057a9eb4b 100644 --- a/src/particles/shaders/imageparticle.vert +++ b/src/particles/shaders/imageparticle.vert @@ -69,11 +69,7 @@ void main() fTex = vPosTex.zw; #endif highp float currentSize = mix(vData.z, vData.w, t * t); -#if defined (Q_OS_BLACKBERRY) - highp float fade = 1.; -#else lowp float fade = 1.; -#endif highp float fadeIn = min(t * 10., 1.); highp float fadeOut = 1. - clamp((t - 0.75) * 4.,0., 1.); @@ -142,4 +138,4 @@ void main() #endif } } -} \ No newline at end of file +} diff --git a/src/particles/shaders/imageparticle_core.vert b/src/particles/shaders/imageparticle_core.vert index ed9a918eb3..cfa0d57dfd 100644 --- a/src/particles/shaders/imageparticle_core.vert +++ b/src/particles/shaders/imageparticle_core.vert @@ -69,11 +69,7 @@ void main() fTex = vPosTex.zw; #endif float currentSize = mix(vData.z, vData.w, t * t); -#if defined (Q_OS_BLACKBERRY) float fade = 1.; -#else - float fade = 1.; -#endif float fadeIn = min(t * 10., 1.); float fadeOut = 1. - clamp((t - 0.75) * 4.,0., 1.); @@ -142,4 +138,4 @@ void main() #endif } } -} \ No newline at end of file +} diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index df7d2806b9..f59b9136a3 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -436,7 +436,6 @@ The following functions are also on the Qt object. \list \li \c "android" - Android - \li \c "blackberry" - BlackBerry OS \li \c "ios" - iOS \li \c "tvos" - tvOS \li \c "linux" - Linux diff --git a/src/qml/qml/qqmlplatform.cpp b/src/qml/qml/qqmlplatform.cpp index a47a0ab4a4..bef79a5ad0 100644 --- a/src/qml/qml/qqmlplatform.cpp +++ b/src/qml/qml/qqmlplatform.cpp @@ -59,8 +59,6 @@ QString QQmlPlatform::os() { #if defined(Q_OS_ANDROID) return QStringLiteral("android"); -#elif defined(Q_OS_BLACKBERRY) - return QStringLiteral("blackberry"); #elif defined(Q_OS_IOS) return QStringLiteral("ios"); #elif defined(Q_OS_TVOS) diff --git a/src/quick/items/qquickflickablebehavior_p.h b/src/quick/items/qquickflickablebehavior_p.h index 3377728d3f..ae7fe71359 100644 --- a/src/quick/items/qquickflickablebehavior_p.h +++ b/src/quick/items/qquickflickablebehavior_p.h @@ -75,20 +75,12 @@ // The default maximum velocity of a flick. #ifndef QML_FLICK_DEFAULTMAXVELOCITY -#ifdef Q_OS_BLACKBERRY -#define QML_FLICK_DEFAULTMAXVELOCITY 10000 -#else -#define QML_FLICK_DEFAULTMAXVELOCITY 2500 -#endif +# define QML_FLICK_DEFAULTMAXVELOCITY 2500 #endif // The default deceleration of a flick. #ifndef QML_FLICK_DEFAULTDECELERATION -#ifdef Q_OS_BLACKBERRY -#define QML_FLICK_DEFAULTDECELERATION 5000 -#else -#define QML_FLICK_DEFAULTDECELERATION 1500 -#endif +# define QML_FLICK_DEFAULTDECELERATION 1500 #endif // How much faster to decelerate when overshooting diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index cb5e17c71e..5fa74027c1 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -280,7 +280,7 @@ public: , stopEventProcessing(false) { sgrc = static_cast(renderContext); -#if defined(Q_OS_QNX) && !defined(Q_OS_BLACKBERRY) && defined(Q_PROCESSOR_X86) +#if defined(Q_OS_QNX) && defined(Q_PROCESSOR_X86) // The SDP 6.6.0 x86 MESA driver requires a larger stack than the default. setStackSize(1024 * 1024); #endif diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp index 0b48c34b92..4699f947a1 100644 --- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp +++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp @@ -309,10 +309,6 @@ void tst_qquickimage::mirror() qreal devicePixelRatio = 1.0; foreach (QQuickImage::FillMode fillMode, fillModes) { -#if defined(Q_OS_BLACKBERRY) - QWindow dummy; // On BlackBerry first window is always full screen, - dummy.showFullScreen(); // so make test window a second window. -#endif QScopedPointer window(new QQuickView); window->setSource(testFileUrl("mirror.qml")); diff --git a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp index 44310008d6..5419778cfc 100644 --- a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp +++ b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp @@ -44,10 +44,6 @@ public: QImage runTest(const QString &fileName) { -#if defined(Q_OS_BLACKBERRY) - QWindow dummy; // On BlackBerry first window is always full screen, - dummy.showFullScreen(); // so make test window a second window. -#endif QQuickView view; view.setSource(testFileUrl(fileName)); diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp index 2032f72e26..034ea4aec8 100644 --- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp +++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp @@ -762,11 +762,6 @@ void tst_qquicktext::horizontalAlignment() void tst_qquicktext::horizontalAlignment_RightToLeft() { -#if defined(Q_OS_BLACKBERRY) - QQuickWindow dummy; // On BlackBerry first window is always full screen, - dummy.showFullScreen(); // so make test window a second window. -#endif - QScopedPointer window(createView(testFile("horizontalAlignment_RightToLeft.qml"))); QQuickText *text = window->rootObject()->findChild("text"); QVERIFY(text != 0); -- cgit v1.2.3 From 36018e06fb3b4263cd01e617205248d82ffae5fa Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 16 Jan 2017 22:20:57 +0100 Subject: Fix up some last un-fixed instances of qmlInfo that should be qmlWarning Seems like I missed some hunks in 3057ec0447943fe022b66a2d19e13d94f9183a7c. Change-Id: I009c838cae856f3fc2e08c7fbc2d3273fc40e221 Reviewed-by: Simon Hausmann --- src/imports/xmllistmodel/qqmlxmllistmodel_p.h | 2 +- src/particles/qquickspritegoal_p.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/imports/xmllistmodel/qqmlxmllistmodel_p.h b/src/imports/xmllistmodel/qqmlxmllistmodel_p.h index 3a4487a085..6605ce9aa6 100644 --- a/src/imports/xmllistmodel/qqmlxmllistmodel_p.h +++ b/src/imports/xmllistmodel/qqmlxmllistmodel_p.h @@ -177,7 +177,7 @@ public: void setQuery(const QString &query) { if (query.startsWith(QLatin1Char('/'))) { - qmlInfo(this) << tr("An XmlRole query must not start with '/'"); + qmlWarning(this) << tr("An XmlRole query must not start with '/'"); return; } if (m_query == query) diff --git a/src/particles/qquickspritegoal_p.h b/src/particles/qquickspritegoal_p.h index 2b15d0b8bb..e569603550 100644 --- a/src/particles/qquickspritegoal_p.h +++ b/src/particles/qquickspritegoal_p.h @@ -107,7 +107,7 @@ void setSystemStates(bool arg) { if (m_systemStates != arg) { //TODO: GroupGoal was added (and this deprecated) Oct 4 - remove it in a few weeks. - qmlInfo(this) << "systemStates is deprecated and will be removed soon. Use GroupGoal instead."; + qmlWarning(this) << "systemStates is deprecated and will be removed soon. Use GroupGoal instead."; m_systemStates = arg; Q_EMIT systemStatesChanged(arg); } -- cgit v1.2.3 From 0412de08fd65c5fef9d010a68b40a256f521ef61 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Tue, 10 Jan 2017 15:49:49 +0100 Subject: qmlInfo: Switch message level to QtInfoMsg, matching the function name qmlInfo predated info-level messages in QtCore, and as such previously sent warning-level messages despite the unfortunate naming. Now that we have an actual qmlWarning function, and we have switched our code to use it, we can change qmlInfo's behavior to better match the function naming. This does have the impact that existing qmlInfo callers will basically need a s/qmlInfo/qmlWarning/g to retain the same QDebug level in user code, but I feel that this behavior change makes sense given the better consistency with C++-side QDebug we attain. [ChangeLog][QtQml][Important Behavior Changes] qmlInfo now reports messages with a QtMsgType of QtInfoMsg instead of QtWarningMsg. To continue to send warnings, callers should migrate to the newly-introduced qmlWarning function. Change-Id: I16c88d94377b5956eb6921b64af7c84d1ca024f6 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlinfo.cpp | 2 +- tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp | 46 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/qml/qml/qqmlinfo.cpp b/src/qml/qml/qqmlinfo.cpp index e87f29753a..dae15e2eca 100644 --- a/src/qml/qml/qqmlinfo.cpp +++ b/src/qml/qml/qqmlinfo.cpp @@ -239,7 +239,7 @@ namespace QtQml { } MESSAGE_FUNCS(qmlDebug, QtMsgType::QtDebugMsg) -MESSAGE_FUNCS(qmlInfo, QtMsgType::QtWarningMsg) // XXX: temporary, switch to QtInfoMsg when callers are ported +MESSAGE_FUNCS(qmlInfo, QtMsgType::QtInfoMsg) MESSAGE_FUNCS(qmlWarning, QtMsgType::QtWarningMsg) diff --git a/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp b/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp index ce3004a31c..3f6c200027 100644 --- a/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp +++ b/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp @@ -63,14 +63,14 @@ void tst_qqmlinfo::qmlObject() QVERIFY(object != 0); QString message = component.url().toString() + ":3:1: QML QtObject: Test Message"; - QTest::ignoreMessage(QtWarningMsg, qPrintable(message)); + QTest::ignoreMessage(QtInfoMsg, qPrintable(message)); qmlInfo(object) << "Test Message"; QObject *nested = qvariant_cast(object->property("nested")); QVERIFY(nested != 0); message = component.url().toString() + ":6:13: QML QtObject: Second Test Message"; - QTest::ignoreMessage(QtWarningMsg, qPrintable(message)); + QTest::ignoreMessage(QtInfoMsg, qPrintable(message)); qmlInfo(nested) << "Second Test Message"; } @@ -87,11 +87,11 @@ void tst_qqmlinfo::nestedQmlObject() QVERIFY(nested2 != 0); QString message = component.url().toString() + ":5:13: QML NestedObject: Outer Object"; - QTest::ignoreMessage(QtWarningMsg, qPrintable(message)); + QTest::ignoreMessage(QtInfoMsg, qPrintable(message)); qmlInfo(nested) << "Outer Object"; message = testFileUrl("NestedObject.qml").toString() + ":6:14: QML QtObject: Inner Object"; - QTest::ignoreMessage(QtWarningMsg, qPrintable(message)); + QTest::ignoreMessage(QtInfoMsg, qPrintable(message)); qmlInfo(nested2) << "Inner Object"; } @@ -108,28 +108,28 @@ void tst_qqmlinfo::nestedComponent() QVERIFY(nested2 != 0); QString message = component.url().toString() + ":10:9: QML NestedObject: Complex Object"; - QTest::ignoreMessage(QtWarningMsg, qPrintable(message)); + QTest::ignoreMessage(QtInfoMsg, qPrintable(message)); qmlInfo(nested) << "Complex Object"; message = component.url().toString() + ":16:9: QML Image: Simple Object"; - QTest::ignoreMessage(QtWarningMsg, qPrintable(message)); + QTest::ignoreMessage(QtInfoMsg, qPrintable(message)); qmlInfo(nested2) << "Simple Object"; } void tst_qqmlinfo::nonQmlObject() { QObject object; - QTest::ignoreMessage(QtWarningMsg, ": QML QtObject: Test Message"); + QTest::ignoreMessage(QtInfoMsg, ": QML QtObject: Test Message"); qmlInfo(&object) << "Test Message"; QTimer nonQmlObject; - QTest::ignoreMessage(QtWarningMsg, ": QML QTimer: Test Message"); + QTest::ignoreMessage(QtInfoMsg, ": QML QTimer: Test Message"); qmlInfo(&nonQmlObject) << "Test Message"; } void tst_qqmlinfo::nullObject() { - QTest::ignoreMessage(QtWarningMsg, ": Null Object Test Message"); + QTest::ignoreMessage(QtInfoMsg, ": Null Object Test Message"); qmlInfo(0) << "Null Object Test Message"; } @@ -138,50 +138,50 @@ void tst_qqmlinfo::nonQmlContextedObject() QObject object; QQmlContext context(&engine); QQmlEngine::setContextForObject(&object, &context); - QTest::ignoreMessage(QtWarningMsg, ": QML QtObject: Test Message"); + QTest::ignoreMessage(QtInfoMsg, ": QML QtObject: Test Message"); qmlInfo(&object) << "Test Message"; } void tst_qqmlinfo::types() { - QTest::ignoreMessage(QtWarningMsg, ": false"); + QTest::ignoreMessage(QtInfoMsg, ": false"); qmlInfo(0) << false; - QTest::ignoreMessage(QtWarningMsg, ": 1.1"); + QTest::ignoreMessage(QtInfoMsg, ": 1.1"); qmlInfo(0) << 1.1; - QTest::ignoreMessage(QtWarningMsg, ": 1.2"); + QTest::ignoreMessage(QtInfoMsg, ": 1.2"); qmlInfo(0) << 1.2f; - QTest::ignoreMessage(QtWarningMsg, ": 15"); + QTest::ignoreMessage(QtInfoMsg, ": 15"); qmlInfo(0) << 15; - QTest::ignoreMessage(QtWarningMsg, ": 'b'"); + QTest::ignoreMessage(QtInfoMsg, ": 'b'"); qmlInfo(0) << QChar('b'); - QTest::ignoreMessage(QtWarningMsg, ": \"Qt\""); + QTest::ignoreMessage(QtInfoMsg, ": \"Qt\""); qmlInfo(0) << QByteArray("Qt"); - QTest::ignoreMessage(QtWarningMsg, ": true"); + QTest::ignoreMessage(QtInfoMsg, ": true"); qmlInfo(0) << bool(true); //### do we actually want QUrl to show up in the output? //### why the extra space at the end? - QTest::ignoreMessage(QtWarningMsg, ": QUrl(\"http://www.qt-project.org\") "); + QTest::ignoreMessage(QtInfoMsg, ": QUrl(\"http://www.qt-project.org\") "); qmlInfo(0) << QUrl("http://www.qt-project.org"); //### should this be quoted? - QTest::ignoreMessage(QtWarningMsg, ": hello"); + QTest::ignoreMessage(QtInfoMsg, ": hello"); qmlInfo(0) << QLatin1String("hello"); //### should this be quoted? - QTest::ignoreMessage(QtWarningMsg, ": World"); + QTest::ignoreMessage(QtInfoMsg, ": World"); QString str("Hello World"); QStringRef ref(&str, 6, 5); qmlInfo(0) << ref; //### should this be quoted? - QTest::ignoreMessage(QtWarningMsg, ": Quick"); + QTest::ignoreMessage(QtInfoMsg, ": Quick"); qmlInfo(0) << QString ("Quick"); } @@ -189,7 +189,7 @@ void tst_qqmlinfo::chaining() { QString str("Hello World"); QStringRef ref(&str, 6, 5); - QTest::ignoreMessage(QtWarningMsg, ": false 1.1 1.2 15 hello 'b' World \"Qt\" true Quick QUrl(\"http://www.qt-project.org\") "); + QTest::ignoreMessage(QtInfoMsg, ": false 1.1 1.2 15 hello 'b' World \"Qt\" true Quick QUrl(\"http://www.qt-project.org\") "); qmlInfo(0) << false << ' ' << 1.1 << ' ' << 1.2f << ' ' @@ -209,7 +209,7 @@ void tst_qqmlinfo::messageTypes() QTest::ignoreMessage(QtDebugMsg, ": debug"); qmlDebug(0) << QLatin1String("debug"); - QTest::ignoreMessage(QtWarningMsg, ": info"); + QTest::ignoreMessage(QtInfoMsg, ": info"); qmlInfo(0) << QLatin1String("info"); QTest::ignoreMessage(QtWarningMsg, ": warning"); -- cgit v1.2.3 From 66c2513f2abceb38fd5770bb915b35b1b15bb69a Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Thu, 12 Jan 2017 12:55:32 +0100 Subject: QQuickGravityAffector: Move implementations from header to cpp These are not performance-critical, so it's cleaner to do this. Change-Id: I6a876636d50e2bfe25f9e6e882d9a98dc032101e Reviewed-by: Shawn Rutledge --- src/particles/qquickgravity.cpp | 41 ++++++++++++++++++++++++++++++++++++++++ src/particles/qquickgravity_p.h | 42 +++++------------------------------------ 2 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/particles/qquickgravity.cpp b/src/particles/qquickgravity.cpp index 90f305f336..835790ce7d 100644 --- a/src/particles/qquickgravity.cpp +++ b/src/particles/qquickgravity.cpp @@ -64,16 +64,54 @@ const qreal CONV = 0.017453292520444443; Pixels per second that objects will be accelerated by. */ +void QQuickGravityAffector::setMagnitude(qreal arg) +{ + if (m_magnitude != arg) { + m_magnitude = arg; + m_needRecalc = true; + emit magnitudeChanged(arg); + } +} + +qreal QQuickGravityAffector::magnitude() const +{ + return m_magnitude; +} + + /*! \qmlproperty real QtQuick.Particles::Gravity::acceleration Name changed to magnitude, will be removed soon. */ +void QQuickGravityAffector::setAcceleration(qreal arg) +{ + qWarning() << "Gravity::acceleration has been renamed Gravity::magnitude"; + if (m_magnitude != arg) { + m_magnitude = arg; + m_needRecalc = true; + emit magnitudeChanged(arg); + } +} + /*! \qmlproperty real QtQuick.Particles::Gravity::angle Angle of acceleration. */ +void QQuickGravityAffector::setAngle(qreal arg) +{ + if (m_angle != arg) { + m_angle = arg; + m_needRecalc = true; + emit angleChanged(arg); + } +} + +qreal QQuickGravityAffector::angle() const +{ + return m_angle; +} QQuickGravityAffector::QQuickGravityAffector(QQuickItem *parent) : QQuickParticleAffector(parent), m_magnitude(-10), m_angle(90), m_needRecalc(true) @@ -94,4 +132,7 @@ bool QQuickGravityAffector::affectParticle(QQuickParticleData *d, qreal dt) d->setInstantaneousVY(d->curVY(m_system) + m_dy*dt, m_system); return true; } + + + QT_END_NAMESPACE diff --git a/src/particles/qquickgravity_p.h b/src/particles/qquickgravity_p.h index d3a7f6665c..333d3d1534 100644 --- a/src/particles/qquickgravity_p.h +++ b/src/particles/qquickgravity_p.h @@ -62,52 +62,20 @@ class QQuickGravityAffector : public QQuickParticleAffector Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged) public: explicit QQuickGravityAffector(QQuickItem *parent = 0); - qreal magnitude() const - { - return m_magnitude; - } + qreal magnitude() const; + qreal angle() const; - qreal angle() const - { - return m_angle; - } protected: bool affectParticle(QQuickParticleData *d, qreal dt) override; Q_SIGNALS: - void magnitudeChanged(qreal arg); - void angleChanged(qreal arg); public Q_SLOTS: -void setAcceleration(qreal arg) -{ - qWarning() << "Gravity::acceleration has been renamed Gravity::magnitude"; - if (m_magnitude != arg) { - m_magnitude = arg; - m_needRecalc = true; - Q_EMIT magnitudeChanged(arg); - } -} - -void setMagnitude(qreal arg) -{ - if (m_magnitude != arg) { - m_magnitude = arg; - m_needRecalc = true; - Q_EMIT magnitudeChanged(arg); - } -} - -void setAngle(qreal arg) -{ - if (m_angle != arg) { - m_angle = arg; - m_needRecalc = true; - Q_EMIT angleChanged(arg); - } -} + void setMagnitude(qreal arg); + void setAcceleration(qreal arg); + void setAngle(qreal arg); private: qreal m_magnitude; -- cgit v1.2.3 From f88ac80a28467648f5e0c5c3d7dc978c4967af4c Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Thu, 12 Jan 2017 13:02:35 +0100 Subject: QQuickGravityAffector: Properly deprecate the acceleration property in docs While we're here, deduplicate the implementation (just forward to the "right" setter), and change qWarning to qmlWarning to get context information on the source of the setter. Change-Id: I32acfee10dd34905bb2c472408e3abc6fa56a386 Reviewed-by: Shawn Rutledge --- src/particles/qquickgravity.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/particles/qquickgravity.cpp b/src/particles/qquickgravity.cpp index 835790ce7d..a2a2ad7e0e 100644 --- a/src/particles/qquickgravity.cpp +++ b/src/particles/qquickgravity.cpp @@ -37,6 +37,7 @@ ** ****************************************************************************/ +#include #include "qquickgravity_p.h" #include QT_BEGIN_NAMESPACE @@ -81,17 +82,14 @@ qreal QQuickGravityAffector::magnitude() const /*! \qmlproperty real QtQuick.Particles::Gravity::acceleration + \deprecated - Name changed to magnitude, will be removed soon. + \warning The name for this property has changed to magnitude, use it instead. */ void QQuickGravityAffector::setAcceleration(qreal arg) { - qWarning() << "Gravity::acceleration has been renamed Gravity::magnitude"; - if (m_magnitude != arg) { - m_magnitude = arg; - m_needRecalc = true; - emit magnitudeChanged(arg); - } + qmlWarning(this) << "The acceleration property is deprecated. Please use magnitude instead."; + setMagnitude(arg); } /*! -- cgit v1.2.3 From 7ed968be5564d8c19d918a3ce8e0683c162f4f1b Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 16 Jan 2017 21:36:27 +0100 Subject: qml: Remove last foreach, and mark QT_NO_FOREACH Just src/imports/ to go... Change-Id: Ib4484676e24655cb950b3c4bb6495ff0e7f9700f Reviewed-by: Simon Hausmann --- src/qml/compiler/qv4ssa.cpp | 2 +- src/qml/jit/qv4regalloc.cpp | 4 ++-- src/qml/qml.pro | 2 ++ src/qml/qml/qqmltypeloader.cpp | 2 +- src/qml/types/qqmlconnections.cpp | 4 ++-- src/qml/types/qqmldelegatemodel.cpp | 8 +++++--- 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp index 943700de44..1d512711b8 100644 --- a/src/qml/compiler/qv4ssa.cpp +++ b/src/qml/compiler/qv4ssa.cpp @@ -2758,7 +2758,7 @@ public: visit(s); } - foreach (const Conversion &conversion, _conversions) { + for (const Conversion &conversion : qAsConst(_conversions)) { IR::Move *move = conversion.stmt->asMove(); // Note: isel only supports move into member when source is a temp, so convert diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index 63d542b5c8..3fb0815299 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -1087,12 +1087,12 @@ private: if (_info->def(it->temp()) != successorStart && !it->isSplitFromInterval()) { const int successorEnd = successor->terminator()->id(); const int idx = successor->in.indexOf(predecessor); - foreach (const Use &use, _info->uses(it->temp())) { + for (const Use &use : _info->uses(it->temp)) { if (use.pos == static_cast(successorStart)) { // only check the current edge, not all other possible ones. This is // important for phi nodes: they have uses that are only valid when // coming in over a specific edge. - foreach (Stmt *s, successor->statements()) { + for (Stmt *s : successor->statements()) { if (Phi *phi = s->asPhi()) { Q_ASSERT(it->temp().index != phi->targetTemp->index); Q_ASSERT(phi->d->incoming[idx]->asTemp() == 0 diff --git a/src/qml/qml.pro b/src/qml/qml.pro index 826a074701..8f9e4b7f83 100644 --- a/src/qml/qml.pro +++ b/src/qml/qml.pro @@ -14,6 +14,8 @@ solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2 # Ensure this gcc optimization is switched off for mips platforms to avoid trouble with JIT. gcc:isEqual(QT_ARCH, "mips"): QMAKE_CXXFLAGS += -fno-reorder-blocks +DEFINES += QT_NO_FOREACH + exists("qqml_enable_gcov") { QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage -fno-elide-constructors LIBS_PRIVATE += -lgcov diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 76ac15e2f1..ac993a1037 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2428,7 +2428,7 @@ void QQmlTypeData::continueLoadFromIR() QList errors; - foreach (const QV4::CompiledData::Import *import, m_document->imports) { + for (const QV4::CompiledData::Import *import : qAsConst(m_document->imports)) { if (!addImport(import, &errors)) { Q_ASSERT(errors.size()); QQmlError error(errors.takeFirst()); diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp index 864ecf54dd..870aeaa6e2 100644 --- a/src/qml/types/qqmlconnections.cpp +++ b/src/qml/types/qqmlconnections.cpp @@ -168,7 +168,7 @@ void QQmlConnections::setTarget(QObject *obj) if (d->targetSet && d->target == obj) return; d->targetSet = true; // even if setting to 0, it is *set* - foreach (QQmlBoundSignal *s, d->boundsignals) { + for (QQmlBoundSignal *s : qAsConst(d->boundsignals)) { // It is possible that target is being changed due to one of our signal // handlers -> use deleteLater(). if (s->isNotifying()) @@ -278,7 +278,7 @@ void QQmlConnections::connectSignals() QQmlContextData *ctxtdata = ddata ? ddata->outerContext : 0; const QV4::CompiledData::Unit *qmlUnit = d->compilationUnit->data; - foreach (const QV4::CompiledData::Binding *binding, d->bindings) { + for (const QV4::CompiledData::Binding *binding : qAsConst(d->bindings)) { Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Script); QString propName = qmlUnit->stringAt(binding->propertyNameIndex); diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index c635ccf79c..c0d75cae33 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -264,7 +264,7 @@ QQmlDelegateModel::~QQmlDelegateModel() { Q_D(QQmlDelegateModel); - foreach (QQmlDelegateModelItem *cacheItem, d->m_cache) { + for (QQmlDelegateModelItem *cacheItem : qAsConst(d->m_cache)) { if (cacheItem->object) { delete cacheItem->object; @@ -764,7 +764,8 @@ void QQmlDelegateModelPrivate::updateFilterGroup() emit q->countChanged(); if (m_parts) { - foreach (QQmlPartsModel *model, m_parts->models) + auto partsCopy = m_parts->models; // deliberate; this may alter m_parts + for (QQmlPartsModel *model : qAsConst(partsCopy)) model->updateFilterGroup(m_compositorGroup, changeSet); } } @@ -1472,7 +1473,8 @@ void QQmlDelegateModelPrivate::emitChanges() for (int i = 1; i < m_groupCount; ++i) QQmlDelegateModelGroupPrivate::get(m_groups[i])->emitModelUpdated(reset); - foreach (QQmlDelegateModelItem *cacheItem, m_cache) { + auto cacheCopy = m_cache; // deliberate; emitChanges may alter m_cache + for (QQmlDelegateModelItem *cacheItem : qAsConst(cacheCopy)) { if (cacheItem->attached) cacheItem->attached->emitChanges(); } -- cgit v1.2.3 From 776eb2162d0fbeabb6af276f4b85865f97a350e3 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 17 Jan 2017 14:22:01 +0100 Subject: QQuickListView: use C++11 range for loops for visible items Change-Id: I0e60c54281cf6838845400fe1a7cf5f2b3a14d65 Reviewed-by: Robin Burchell --- src/quick/items/qquicklistview.cpp | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 5a39ff9422..63d1ac2506 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -531,8 +531,7 @@ FxViewItem *QQuickListViewPrivate::snapItemAt(qreal pos) { FxViewItem *snapItem = 0; qreal prevItemSize = 0; - for (int i = 0; i < visibleItems.count(); ++i) { - FxViewItem *item = visibleItems.at(i); + for (FxViewItem *item : qAsConst(visibleItems)) { if (item->index == -1) continue; qreal itemTop = item->position(); @@ -661,8 +660,8 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal int newModelIdx = qBound(0, modelIndex + count, model->count()); count = newModelIdx - modelIndex; if (count) { - for (int i = 0; i < visibleItems.count(); ++i) - releaseItem(visibleItems.at(i)); + for (FxViewItem *item : qAsConst(visibleItems)) + releaseItem(item); visibleItems.clear(); modelIndex = newModelIdx; visibleIndex = modelIndex; @@ -1009,8 +1008,8 @@ void QQuickListViewPrivate::releaseSectionItem(QQuickItem *item) void QQuickListViewPrivate::releaseSectionItems() { - for (int i = 0; i < visibleItems.count(); ++i) { - FxListItemSG *listItem = static_cast(visibleItems.at(i)); + for (FxViewItem *item : qAsConst(visibleItems)) { + FxListItemSG *listItem = static_cast(item); if (listItem->section()) { qreal pos = listItem->position(); releaseSectionItem(listItem->section()); @@ -1169,8 +1168,7 @@ void QQuickListViewPrivate::updateSections() QQuickListViewAttached *prevAtt = 0; int prevIdx = -1; int idx = -1; - for (int i = 0; i < visibleItems.count(); ++i) { - FxViewItem *item = visibleItems.at(i); + for (FxViewItem *item : qAsConst(visibleItems)) { QQuickListViewAttached *attached = static_cast(item->attached); attached->setPrevSection(prevSection); if (item->index != -1) { @@ -1295,8 +1293,8 @@ void QQuickListViewPrivate::updateAverage() if (!visibleItems.count()) return; qreal sum = 0.0; - for (int i = 0; i < visibleItems.count(); ++i) - sum += visibleItems.at(i)->size(); + for (FxViewItem *item : qAsConst(visibleItems)) + sum += item->size(); averageSize = qRound(sum / visibleItems.count()); } @@ -2933,8 +2931,7 @@ void QQuickListView::viewportMoved(Qt::Orientations orient) // Set visibility of items to eliminate cost of items outside the visible area. qreal from = d->isContentFlowReversed() ? -d->position()-d->displayMarginBeginning-d->size() : d->position()-d->displayMarginBeginning; qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd; - for (int i = 0; i < d->visibleItems.count(); ++i) { - FxViewItem *item = static_cast(d->visibleItems.at(i)); + for (FxViewItem *item : qAsConst(d->visibleItems)) { if (item->item) QQuickItemPrivate::get(item->item)->setCulled(item->endPosition() < from || item->position() > to); } @@ -3169,8 +3166,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch if (modelIndex < visibleIndex) { // Insert before visible items visibleIndex += count; - for (int i = 0; i < visibleItems.count(); ++i) { - FxViewItem *item = visibleItems.at(i); + for (FxViewItem *item : qAsConst(visibleItems)) { if (item->index != -1 && item->index >= modelIndex) item->index += count; } @@ -3187,8 +3183,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch } // Update the indexes of the following visible items. - for (int i = 0; i < visibleItems.count(); ++i) { - FxViewItem *item = visibleItems.at(i); + for (FxViewItem *item : qAsConst(visibleItems)) { if (item->index != -1 && item->index >= modelIndex) { item->index += count; if (change.isMove()) -- cgit v1.2.3 From ca7ac31ab2123f8eb89876d9a5db67351add752f Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 17 Jan 2017 14:36:50 +0100 Subject: QQuickGridView: use C++11 range for loops for visible items Change-Id: If168e24e3e240182707602071125ac3538703fe7 Reviewed-by: Robin Burchell --- src/quick/items/qquickgridview.cpp | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp index 4359700362..7090ad82ca 100644 --- a/src/quick/items/qquickgridview.cpp +++ b/src/quick/items/qquickgridview.cpp @@ -383,8 +383,7 @@ qreal QQuickGridViewPrivate::snapPosAt(qreal pos) const FxViewItem *QQuickGridViewPrivate::snapItemAt(qreal pos) const { - for (int i = 0; i < visibleItems.count(); ++i) { - FxViewItem *item = visibleItems.at(i); + for (FxViewItem *item : visibleItems) { if (item->index == -1) continue; qreal itemTop = item->position(); @@ -397,16 +396,16 @@ FxViewItem *QQuickGridViewPrivate::snapItemAt(qreal pos) const int QQuickGridViewPrivate::snapIndex() const { int index = currentIndex; - for (int i = 0; i < visibleItems.count(); ++i) { - FxGridItemSG *item = static_cast(visibleItems.at(i)); + for (FxViewItem *item : visibleItems) { if (item->index == -1) continue; qreal itemTop = item->position(); FxGridItemSG *hItem = static_cast(highlight); if (itemTop >= hItem->rowPos()-rowSize()/2 && itemTop < hItem->rowPos()+rowSize()/2) { - index = item->index; - if (item->colPos() >= hItem->colPos()-colSize()/2 && item->colPos() < hItem->colPos()+colSize()/2) - return item->index; + FxGridItemSG *gridItem = static_cast(item); + index = gridItem->index; + if (gridItem->colPos() >= hItem->colPos()-colSize()/2 && gridItem->colPos() < hItem->colPos()+colSize()/2) + return gridItem->index; } } return index; @@ -496,8 +495,8 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal // We've jumped more than a page. Estimate which items are now // visible and fill from there. int count = (fillFrom - (rowPos + rowSize())) / (rowSize()) * columns; - for (int i = 0; i < visibleItems.count(); ++i) - releaseItem(visibleItems.at(i)); + for (FxViewItem *item : qAsConst(visibleItems)) + releaseItem(item); visibleItems.clear(); modelIndex += count; if (modelIndex >= model->count()) @@ -2055,9 +2054,9 @@ void QQuickGridView::viewportMoved(Qt::Orientations orient) // Set visibility of items to eliminate cost of items outside the visible area. qreal from = d->isContentFlowReversed() ? -d->position()-d->displayMarginBeginning-d->size() : d->position()-d->displayMarginBeginning; qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd; - for (int i = 0; i < d->visibleItems.count(); ++i) { - FxGridItemSG *item = static_cast(d->visibleItems.at(i)); - QQuickItemPrivate::get(item->item)->setCulled(item->rowPos() + d->rowSize() < from || item->rowPos() > to); + for (FxViewItem *item : qAsConst(d->visibleItems)) { + FxGridItemSG *gridItem = static_cast(item); + QQuickItemPrivate::get(gridItem->item)->setCulled(gridItem->rowPos() + d->rowSize() < from || gridItem->rowPos() > to); } if (d->currentItem) { FxGridItemSG *item = static_cast(d->currentItem); @@ -2357,8 +2356,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch if (modelIndex <= visibleIndex) { // Insert before visible items visibleIndex += count; - for (int i = 0; i < visibleItems.count(); ++i) { - FxViewItem *item = visibleItems.at(i); + for (FxViewItem *item : qAsConst(visibleItems)) { if (item->index != -1 && item->index >= modelIndex) item->index += count; } @@ -2391,8 +2389,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch } // Update the indexes of the following visible items. - for (int i = 0; i < visibleItems.count(); ++i) { - FxViewItem *item = visibleItems.at(i); + for (FxViewItem *item : qAsConst(visibleItems)) { if (item->index != -1 && item->index >= modelIndex) { item->index += count; if (change.isMove()) -- cgit v1.2.3 From 89c6bee139422b17534f79129eea2820d2ce952e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 16 Jan 2017 16:28:31 +0100 Subject: Fix support for QJSValue as C++ signal parameter type, part 2 After commit 0e3380f9c6ab6e3ea7398caccf5aa84f1575f1cd we wouldn't crash anymore, if QJSValue::UndefinedValue was provided as value for a QJSValue C++ signal parameter. However that was not a complete fix for the regression of commit aa869cbb06bcf005e238059a2cb0205947ff0b5f, as other primitive values stored in QJSValue as QVariant were not converted, so for example QJSValue(42). So let's fix this once and for all by using QJSValuePrivate::valueForData, that handles all types of QJSValuePrivate encodings. Task-number: QTBUG-58133 Change-Id: Ib7c0461b18df6260ccd4bce729ae2348281eb7f3 Reviewed-by: Arnaud Vrac Reviewed-by: Lars Knoll --- src/qml/qml/qqmlboundsignal.cpp | 2 +- tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml | 8 +++++++- tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 7 ++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index d207a4908c..1fdb0d2e25 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -199,7 +199,7 @@ void QQmlBoundSignalExpression::evaluate(void **a) // for several cases (such as QVariant type and QObject-derived types) //args[ii] = engine->metaTypeToJS(type, a[ii + 1]); if (type == qMetaTypeId()) { - if (QV4::Value *v4Value = QJSValuePrivate::getValue(reinterpret_cast(a[ii + 1]))) + if (QV4::Value *v4Value = QJSValuePrivate::valueForData(reinterpret_cast(a[ii + 1]), &callData->args[ii])) callData->args[ii] = *v4Value; else callData->args[ii] = QV4::Encode::undefined(); diff --git a/tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml b/tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml index 676593096c..54d29dfc94 100644 --- a/tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml +++ b/tests/auto/qml/qqmlecmascript/data/signalParameterTypes.qml @@ -16,5 +16,11 @@ MyQmlObject onBasicSignal: root.mySignal(10, 19.2, Qt.rgba(1, 1, 0, 1), Qt.rgba(1, 0, 1, 1), MyQmlObject.EnumValue3, Qt.LeftButton) - onQjsValueEmittingSignal: {} + property bool emittedQjsValueWasUndefined + property int emittedQjsValueAsInt + + onQjsValueEmittingSignal: { + emittedQjsValueWasUndefined = value === undefined; + emittedQjsValueAsInt = value + } } diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index b8f12e772d..20f7940e9d 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -1410,7 +1410,6 @@ void tst_qqmlecmascript::signalParameterTypes() QVERIFY(object != 0); emit object->basicSignal(); - emit object->qjsValueEmittingSignal(QJSValue()); QCOMPARE(object->property("intProperty").toInt(), 10); QCOMPARE(object->property("realProperty").toReal(), 19.2); @@ -1419,6 +1418,12 @@ void tst_qqmlecmascript::signalParameterTypes() QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3); QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton); + emit object->qjsValueEmittingSignal(QJSValue()); + QVERIFY(object->property("emittedQjsValueWasUndefined").toBool()); + emit object->qjsValueEmittingSignal(QJSValue(42)); + QVERIFY(!object->property("emittedQjsValueWasUndefined").toBool()); + QCOMPARE(object->property("emittedQjsValueAsInt").value(), 42); + delete object; } -- cgit v1.2.3 From e8089fe3f64211d780407210b548d9c3d392e343 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 17 Jan 2017 14:52:50 +0100 Subject: QQuickItemView: use some more C++11 range for loops Change-Id: Ief706dfce0c81351ac06b8791267107ad8165974 Reviewed-by: Robin Burchell --- src/quick/items/qquickitemview.cpp | 69 +++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 3f097d4bc8..a8bac633cc 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -380,8 +380,8 @@ void QQuickItemView::setDelegate(QQmlComponent *delegate) int oldCount = dataModel->count(); dataModel->setDelegate(delegate); if (isComponentComplete()) { - for (int i = 0; i < d->visibleItems.count(); ++i) - d->releaseItem(d->visibleItems.at(i)); + for (FxViewItem *item : qAsConst(d->visibleItems)) + d->releaseItem(item); d->visibleItems.clear(); d->releaseItem(d->currentItem); d->currentItem = 0; @@ -946,12 +946,12 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode) qreal itemPos = positionAt(idx); changedVisibleIndex(idx); // save the currently visible items in case any of them end up visible again - QList oldVisible = visibleItems; + const QList oldVisible = visibleItems; visibleItems.clear(); setPosition(qMin(itemPos, maxExtent)); // now release the reference to all the old visible items. - for (int i = 0; i < oldVisible.count(); ++i) - releaseItem(oldVisible.at(i)); + for (FxViewItem *item : oldVisible) + releaseItem(item); item = visibleItem(idx); } if (item) { @@ -1199,10 +1199,10 @@ void QQuickItemViewPrivate::checkVisible() const void QQuickItemViewPrivate::showVisibleItems() const { qDebug() << "Visible items:"; - for (int i = 0; i < visibleItems.count(); ++i) { - qDebug() << "\t" << visibleItems.at(i)->index - << visibleItems.at(i)->item->objectName() - << visibleItems.at(i)->position(); + for (FxViewItem *item : visibleItems) { + qDebug() << "\t" << item->index + << item->item->objectName() + << item->position(); } } @@ -1646,8 +1646,7 @@ FxViewItem *QQuickItemViewPrivate::visibleItem(int modelIndex) const { // that don't look at the view position and size FxViewItem *QQuickItemViewPrivate::firstVisibleItem() const { const qreal pos = isContentFlowReversed() ? -position()-size() : position(); - for (int i = 0; i < visibleItems.count(); ++i) { - FxViewItem *item = visibleItems.at(i); + for (FxViewItem *item : visibleItems) { if (item->index != -1 && item->endPosition() > pos) return item; } @@ -1744,14 +1743,14 @@ void QQuickItemViewPrivate::clear() currentChanges.reset(); timeline.clear(); - for (int i = 0; i < visibleItems.count(); ++i) - releaseItem(visibleItems.at(i)); + for (FxViewItem *item : qAsConst(visibleItems)) + releaseItem(item); visibleItems.clear(); visibleIndex = 0; - for (int i = 0; i < releasePendingTransition.count(); ++i) { - releasePendingTransition.at(i)->releaseAfterTransition = false; - releaseItem(releasePendingTransition.at(i)); + for (FxViewItem *item : qAsConst(releasePendingTransition)) { + item->releaseAfterTransition = false; + releaseItem(item); } releasePendingTransition.clear(); @@ -1912,9 +1911,9 @@ void QQuickItemViewPrivate::layout() forceLayout = false; if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) { - for (int i=0; itransitionScheduledOrRunning()) - visibleItems.at(i)->transitionNextReposition(transitioner, QQuickItemViewTransitioner::PopulateTransition, true); + for (FxViewItem *item : qAsConst(visibleItems)) { + if (!item->transitionScheduledOrRunning()) + item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::PopulateTransition, true); } } @@ -2010,18 +2009,18 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult ChangeResult removalResult(prevViewPos); int removedCount = 0; - for (int i=0; i= 0 && removals[i].index < correctedFirstVisibleIndex) { - if (removals[i].index + removals[i].count < correctedFirstVisibleIndex) - removalResult.countChangeBeforeVisible += removals[i].count; + if (correctedFirstVisibleIndex >= 0 && r.index < correctedFirstVisibleIndex) { + if (r.index + r.count < correctedFirstVisibleIndex) + removalResult.countChangeBeforeVisible += r.count; else - removalResult.countChangeBeforeVisible += (correctedFirstVisibleIndex - removals[i].index); + removalResult.countChangeBeforeVisible += (correctedFirstVisibleIndex - r.index); } } if (runDelayedRemoveTransition) { @@ -2068,23 +2067,23 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult } itemCount += insertions[i].count; } - for (int i=0; iattached) - newItems.at(i)->attached->emitAdd(); + for (FxViewItem *item : qAsConst(newItems)) { + if (item->attached) + item->attached->emitAdd(); } // for each item that was moved directly into the view as a result of a move(), // find the index it was moved from in order to set its initial position, so that we // can transition it from this "original" position to its new position in the view if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition, true)) { - for (int i=0; i= 0) { if (prevFirstVisibleIndex >= 0 && fromIndex < prevFirstVisibleIndex) - repositionItemAt(movingIntoView.at(i).item, fromIndex, -totalInsertionResult->sizeChangesAfterVisiblePos); + repositionItemAt(m.item, fromIndex, -totalInsertionResult->sizeChangesAfterVisiblePos); else - repositionItemAt(movingIntoView.at(i).item, fromIndex, totalInsertionResult->sizeChangesAfterVisiblePos); - movingIntoView.at(i).item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition, true); + repositionItemAt(m.item, fromIndex, totalInsertionResult->sizeChangesAfterVisiblePos); + m.item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition, true); } } } -- cgit v1.2.3 From 7e7138517ed09363c98986e09ffd966548c27a88 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 17 Jan 2017 16:29:15 +0100 Subject: Item views: Q_DECL_OVERRIDE -> override Change-Id: I7dfbd5f47893a3244c96989ad7eea7e93ea28603 Reviewed-by: Robin Burchell Reviewed-by: Shawn Rutledge --- src/quick/items/qquickgridview.cpp | 88 +++++++++++++------------- src/quick/items/qquickgridview_p.h | 12 ++-- src/quick/items/qquickitemview_p.h | 22 +++---- src/quick/items/qquickitemview_p_p.h | 8 +-- src/quick/items/qquickitemviewtransition.cpp | 2 +- src/quick/items/qquicklistview.cpp | 94 ++++++++++++++-------------- src/quick/items/qquicklistview_p.h | 16 ++--- src/quick/items/qquickpathview_p.h | 14 ++--- src/quick/items/qquickpathview_p_p.h | 2 +- src/quick/items/qquickview.h | 16 ++--- src/quick/items/qquickview_p.h | 2 +- 11 files changed, 138 insertions(+), 138 deletions(-) diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp index 7090ad82ca..e6a7a0acd0 100644 --- a/src/quick/items/qquickgridview.cpp +++ b/src/quick/items/qquickgridview.cpp @@ -66,19 +66,19 @@ public: { } - qreal position() const Q_DECL_OVERRIDE { + qreal position() const override { return rowPos(); } - qreal endPosition() const Q_DECL_OVERRIDE { + qreal endPosition() const override { return endRowPos(); } - qreal size() const Q_DECL_OVERRIDE { + qreal size() const override { return view->flow() == QQuickGridView::FlowLeftToRight ? view->cellHeight() : view->cellWidth(); } - qreal sectionSize() const Q_DECL_OVERRIDE { + qreal sectionSize() const override { return 0.0; } @@ -122,7 +122,7 @@ public: void setPosition(qreal col, qreal row, bool immediate = false) { moveTo(pointForPosition(col, row), immediate); } - bool contains(qreal x, qreal y) const Q_DECL_OVERRIDE { + bool contains(qreal x, qreal y) const override { return (x >= itemX() && x < itemX() + view->cellWidth() && y >= itemY() && y < itemY() + view->cellHeight()); } @@ -159,13 +159,13 @@ class QQuickGridViewPrivate : public QQuickItemViewPrivate Q_DECLARE_PUBLIC(QQuickGridView) public: - Qt::Orientation layoutOrientation() const Q_DECL_OVERRIDE; - bool isContentFlowReversed() const Q_DECL_OVERRIDE; + Qt::Orientation layoutOrientation() const override; + bool isContentFlowReversed() const override; - qreal positionAt(int index) const Q_DECL_OVERRIDE; - qreal endPositionAt(int index) const Q_DECL_OVERRIDE; - qreal originPosition() const Q_DECL_OVERRIDE; - qreal lastPosition() const Q_DECL_OVERRIDE; + qreal positionAt(int index) const override; + qreal endPositionAt(int index) const override; + qreal originPosition() const override; + qreal lastPosition() const override; qreal rowSize() const; qreal colSize() const; @@ -179,43 +179,43 @@ public: void resetColumns(); - bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer) Q_DECL_OVERRIDE; - bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) Q_DECL_OVERRIDE; + bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer) override; + bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) override; void removeItem(FxViewItem *item); - FxViewItem *newViewItem(int index, QQuickItem *item) Q_DECL_OVERRIDE; - void initializeViewItem(FxViewItem *item) Q_DECL_OVERRIDE; - void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer) Q_DECL_OVERRIDE; - void repositionPackageItemAt(QQuickItem *item, int index) Q_DECL_OVERRIDE; - void resetFirstItemPosition(qreal pos = 0.0) Q_DECL_OVERRIDE; - void adjustFirstItem(qreal forwards, qreal backwards, int changeBeforeVisible) Q_DECL_OVERRIDE; - - void createHighlight() Q_DECL_OVERRIDE; - void updateHighlight() Q_DECL_OVERRIDE; - void resetHighlightPosition() Q_DECL_OVERRIDE; - - void setPosition(qreal pos) Q_DECL_OVERRIDE; - void layoutVisibleItems(int fromModelIndex = 0) Q_DECL_OVERRIDE; - bool applyInsertionChange(const QQmlChangeSet::Change &insert, ChangeResult *changeResult, QList *addedItems, QList *movingIntoView) Q_DECL_OVERRIDE; - void translateAndTransitionItemsAfter(int afterModelIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult) Q_DECL_OVERRIDE; - bool needsRefillForAddedOrRemovedIndex(int index) const Q_DECL_OVERRIDE; - - qreal headerSize() const Q_DECL_OVERRIDE; - qreal footerSize() const Q_DECL_OVERRIDE; - bool showHeaderForIndex(int index) const Q_DECL_OVERRIDE; - bool showFooterForIndex(int index) const Q_DECL_OVERRIDE; - void updateHeader() Q_DECL_OVERRIDE; - void updateFooter() Q_DECL_OVERRIDE; - - void changedVisibleIndex(int newIndex) Q_DECL_OVERRIDE; - void initializeCurrentItem() Q_DECL_OVERRIDE; - - void updateViewport() Q_DECL_OVERRIDE; - void fixupPosition() Q_DECL_OVERRIDE; - void fixup(AxisData &data, qreal minExtent, qreal maxExtent) Q_DECL_OVERRIDE; + FxViewItem *newViewItem(int index, QQuickItem *item) override; + void initializeViewItem(FxViewItem *item) override; + void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer) override; + void repositionPackageItemAt(QQuickItem *item, int index) override; + void resetFirstItemPosition(qreal pos = 0.0) override; + void adjustFirstItem(qreal forwards, qreal backwards, int changeBeforeVisible) override; + + void createHighlight() override; + void updateHighlight() override; + void resetHighlightPosition() override; + + void setPosition(qreal pos) override; + void layoutVisibleItems(int fromModelIndex = 0) override; + bool applyInsertionChange(const QQmlChangeSet::Change &insert, ChangeResult *changeResult, QList *addedItems, QList *movingIntoView) override; + void translateAndTransitionItemsAfter(int afterModelIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult) override; + bool needsRefillForAddedOrRemovedIndex(int index) const override; + + qreal headerSize() const override; + qreal footerSize() const override; + bool showHeaderForIndex(int index) const override; + bool showFooterForIndex(int index) const override; + void updateHeader() override; + void updateFooter() override; + + void changedVisibleIndex(int newIndex) override; + void initializeCurrentItem() override; + + void updateViewport() override; + void fixupPosition() override; + void fixup(AxisData &data, qreal minExtent, qreal maxExtent) override; bool flick(QQuickItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, - QQuickTimeLineCallback::Callback fixupCallback, qreal velocity) Q_DECL_OVERRIDE; + QQuickTimeLineCallback::Callback fixupCallback, qreal velocity) override; QQuickGridView::Flow flow; qreal cellWidth; diff --git a/src/quick/items/qquickgridview_p.h b/src/quick/items/qquickgridview_p.h index aaf6e4a75b..5c6da2b433 100644 --- a/src/quick/items/qquickgridview_p.h +++ b/src/quick/items/qquickgridview_p.h @@ -84,8 +84,8 @@ public: QQuickGridView(QQuickItem *parent=0); ~QQuickGridView(); - void setHighlightFollowsCurrentItem(bool) Q_DECL_OVERRIDE; - void setHighlightMoveDuration(int) Q_DECL_OVERRIDE; + void setHighlightFollowsCurrentItem(bool) override; + void setHighlightMoveDuration(int) override; Flow flow() const; void setFlow(Flow); @@ -117,10 +117,10 @@ Q_SIGNALS: void snapModeChanged(); protected: - void viewportMoved(Qt::Orientations) Q_DECL_OVERRIDE; - void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE; - void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; - void initItem(int index, QObject *item) Q_DECL_OVERRIDE; + void viewportMoved(Qt::Orientations) override; + void keyPressEvent(QKeyEvent *) override; + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; + void initItem(int index, QObject *item) override; }; class QQuickGridViewAttached : public QQuickItemViewAttached diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h index 3ac54ea3dc..b38bc6174f 100644 --- a/src/quick/items/qquickitemview_p.h +++ b/src/quick/items/qquickitemview_p.h @@ -232,10 +232,10 @@ public: Q_INVOKABLE void positionViewAtEnd(); Q_REVISION(1) Q_INVOKABLE void forceLayout(); - void setContentX(qreal pos) Q_DECL_OVERRIDE; - void setContentY(qreal pos) Q_DECL_OVERRIDE; - qreal originX() const Q_DECL_OVERRIDE; - qreal originY() const Q_DECL_OVERRIDE; + void setContentX(qreal pos) override; + void setContentY(qreal pos) override; + qreal originX() const override; + qreal originY() const override; Q_SIGNALS: void modelChanged(); @@ -277,13 +277,13 @@ Q_SIGNALS: void highlightMoveDurationChanged(); protected: - void updatePolish() Q_DECL_OVERRIDE; - void componentComplete() Q_DECL_OVERRIDE; - void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; - qreal minYExtent() const Q_DECL_OVERRIDE; - qreal maxYExtent() const Q_DECL_OVERRIDE; - qreal minXExtent() const Q_DECL_OVERRIDE; - qreal maxXExtent() const Q_DECL_OVERRIDE; + void updatePolish() override; + void componentComplete() override; + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; + qreal minYExtent() const override; + qreal maxYExtent() const override; + qreal minXExtent() const override; + qreal maxXExtent() const override; protected Q_SLOTS: void destroyRemoved(); diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h index 4ebb632840..3087682ac7 100644 --- a/src/quick/items/qquickitemview_p_p.h +++ b/src/quick/items/qquickitemview_p_p.h @@ -201,10 +201,10 @@ public: void regenerate(bool orientationChanged=false); void layout(); - virtual void animationFinished(QAbstractAnimationJob *) Q_DECL_OVERRIDE; + virtual void animationFinished(QAbstractAnimationJob *) override; void refill(); void refill(qreal from, qreal to); - void mirrorChange() Q_DECL_OVERRIDE; + void mirrorChange() override; FxViewItem *createItem(int modelIndex, bool asynchronous = false); virtual bool releaseItem(FxViewItem *item); @@ -236,7 +236,7 @@ public: void prepareVisibleItemTransitions(); void prepareRemoveTransitions(QHash *removedItems); bool prepareNonVisibleItemTransition(FxViewItem *item, const QRectF &viewBounds); - void viewItemTransitionFinished(QQuickItemViewTransitionableItem *item) Q_DECL_OVERRIDE; + void viewItemTransitionFinished(QQuickItemViewTransitionableItem *item) override; int findMoveKeyIndex(QQmlChangeSet::MoveKey key, const QVector &changes) const; @@ -382,7 +382,7 @@ protected: virtual void updateSectionCriteria() {} virtual void updateSections() {} - void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) Q_DECL_OVERRIDE; + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) override; }; diff --git a/src/quick/items/qquickitemviewtransition.cpp b/src/quick/items/qquickitemviewtransition.cpp index 83c451613e..700c4cc620 100644 --- a/src/quick/items/qquickitemviewtransition.cpp +++ b/src/quick/items/qquickitemviewtransition.cpp @@ -64,7 +64,7 @@ public: bool *m_wasDeleted; protected: - void finished() Q_DECL_OVERRIDE; + void finished() override; }; diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 63d1ac2506..0351077f20 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -65,51 +65,51 @@ class QQuickListViewPrivate : public QQuickItemViewPrivate public: static QQuickListViewPrivate* get(QQuickListView *item) { return item->d_func(); } - Qt::Orientation layoutOrientation() const Q_DECL_OVERRIDE; - bool isContentFlowReversed() const Q_DECL_OVERRIDE; + Qt::Orientation layoutOrientation() const override; + bool isContentFlowReversed() const override; bool isRightToLeft() const; bool isBottomToTop() const; - qreal positionAt(int index) const Q_DECL_OVERRIDE; - qreal endPositionAt(int index) const Q_DECL_OVERRIDE; - qreal originPosition() const Q_DECL_OVERRIDE; - qreal lastPosition() const Q_DECL_OVERRIDE; + qreal positionAt(int index) const override; + qreal endPositionAt(int index) const override; + qreal originPosition() const override; + qreal lastPosition() const override; FxViewItem *itemBefore(int modelIndex) const; QString sectionAt(int modelIndex); qreal snapPosAt(qreal pos); FxViewItem *snapItemAt(qreal pos); - void init() Q_DECL_OVERRIDE; - void clear() Q_DECL_OVERRIDE; + void init() override; + void clear() override; - bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer) Q_DECL_OVERRIDE; - bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) Q_DECL_OVERRIDE; - void visibleItemsChanged() Q_DECL_OVERRIDE; + bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer) override; + bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) override; + void visibleItemsChanged() override; void removeItem(FxViewItem *item); - FxViewItem *newViewItem(int index, QQuickItem *item) Q_DECL_OVERRIDE; - void initializeViewItem(FxViewItem *item) Q_DECL_OVERRIDE; - bool releaseItem(FxViewItem *item) Q_DECL_OVERRIDE; - void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer) Q_DECL_OVERRIDE; - void repositionPackageItemAt(QQuickItem *item, int index) Q_DECL_OVERRIDE; - void resetFirstItemPosition(qreal pos = 0.0) Q_DECL_OVERRIDE; - void adjustFirstItem(qreal forwards, qreal backwards, int) Q_DECL_OVERRIDE; - void updateSizeChangesBeforeVisiblePos(FxViewItem *item, ChangeResult *removeResult) Q_DECL_OVERRIDE; + FxViewItem *newViewItem(int index, QQuickItem *item) override; + void initializeViewItem(FxViewItem *item) override; + bool releaseItem(FxViewItem *item) override; + void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer) override; + void repositionPackageItemAt(QQuickItem *item, int index) override; + void resetFirstItemPosition(qreal pos = 0.0) override; + void adjustFirstItem(qreal forwards, qreal backwards, int) override; + void updateSizeChangesBeforeVisiblePos(FxViewItem *item, ChangeResult *removeResult) override; - void createHighlight() Q_DECL_OVERRIDE; - void updateHighlight() Q_DECL_OVERRIDE; - void resetHighlightPosition() Q_DECL_OVERRIDE; + void createHighlight() override; + void updateHighlight() override; + void resetHighlightPosition() override; - void setPosition(qreal pos) Q_DECL_OVERRIDE; - void layoutVisibleItems(int fromModelIndex = 0) Q_DECL_OVERRIDE; + void setPosition(qreal pos) override; + void layoutVisibleItems(int fromModelIndex = 0) override; - bool applyInsertionChange(const QQmlChangeSet::Change &insert, ChangeResult *changeResult, QList *addedItems, QList *movingIntoView) Q_DECL_OVERRIDE; - void translateAndTransitionItemsAfter(int afterIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult) Q_DECL_OVERRIDE; + bool applyInsertionChange(const QQmlChangeSet::Change &insert, ChangeResult *changeResult, QList *addedItems, QList *movingIntoView) override; + void translateAndTransitionItemsAfter(int afterIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult) override; - void updateSectionCriteria() Q_DECL_OVERRIDE; - void updateSections() Q_DECL_OVERRIDE; + void updateSectionCriteria() override; + void updateSections() override; QQuickItem *getSectionItem(const QString §ion); void releaseSectionItem(QQuickItem *item); void releaseSectionItems(); @@ -117,25 +117,25 @@ public: void updateCurrentSection(); void updateStickySections(); - qreal headerSize() const Q_DECL_OVERRIDE; - qreal footerSize() const Q_DECL_OVERRIDE; - bool showHeaderForIndex(int index) const Q_DECL_OVERRIDE; - bool showFooterForIndex(int index) const Q_DECL_OVERRIDE; - void updateHeader() Q_DECL_OVERRIDE; - void updateFooter() Q_DECL_OVERRIDE; - bool hasStickyHeader() const Q_DECL_OVERRIDE; - bool hasStickyFooter() const Q_DECL_OVERRIDE; + qreal headerSize() const override; + qreal footerSize() const override; + bool showHeaderForIndex(int index) const override; + bool showFooterForIndex(int index) const override; + void updateHeader() override; + void updateFooter() override; + bool hasStickyHeader() const override; + bool hasStickyFooter() const override; - void changedVisibleIndex(int newIndex) Q_DECL_OVERRIDE; - void initializeCurrentItem() Q_DECL_OVERRIDE; + void changedVisibleIndex(int newIndex) override; + void initializeCurrentItem() override; void updateAverage(); - void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &oldGeometry) Q_DECL_OVERRIDE; - void fixupPosition() Q_DECL_OVERRIDE; - void fixup(AxisData &data, qreal minExtent, qreal maxExtent) Q_DECL_OVERRIDE; + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &oldGeometry) override; + void fixupPosition() override; + void fixup(AxisData &data, qreal minExtent, qreal maxExtent) override; bool flick(QQuickItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, - QQuickTimeLineCallback::Callback fixupCallback, qreal velocity) Q_DECL_OVERRIDE; + QQuickTimeLineCallback::Callback fixupCallback, qreal velocity) override; QQuickListView::Orientation orient; qreal visiblePos; @@ -263,7 +263,7 @@ public: static_cast(attached)->m_sectionItem = s; } - qreal position() const Q_DECL_OVERRIDE { + qreal position() const override { if (section()) { if (view->orientation() == QQuickListView::Vertical) return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop ? -section()->height()-section()->y() : section()->y()); @@ -279,7 +279,7 @@ public: else return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -itemWidth()-itemX() : itemX()); } - qreal size() const Q_DECL_OVERRIDE { + qreal size() const override { if (section()) return (view->orientation() == QQuickListView::Vertical ? itemHeight()+section()->height() : itemWidth()+section()->width()); else @@ -288,12 +288,12 @@ public: qreal itemSize() const { return (view->orientation() == QQuickListView::Vertical ? itemHeight() : itemWidth()); } - qreal sectionSize() const Q_DECL_OVERRIDE { + qreal sectionSize() const override { if (section()) return (view->orientation() == QQuickListView::Vertical ? section()->height() : section()->width()); return 0.0; } - qreal endPosition() const Q_DECL_OVERRIDE { + qreal endPosition() const override { if (view->orientation() == QQuickListView::Vertical) { return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop ? -itemY() @@ -327,7 +327,7 @@ public: else item->setWidth(size); } - bool contains(qreal x, qreal y) const Q_DECL_OVERRIDE { + bool contains(qreal x, qreal y) const override { return (x >= itemX() && x < itemX() + itemWidth() && y >= itemY() && y < itemY() + itemHeight()); } diff --git a/src/quick/items/qquicklistview_p.h b/src/quick/items/qquicklistview_p.h index dbed8dfed4..f8db0f0f8f 100644 --- a/src/quick/items/qquicklistview_p.h +++ b/src/quick/items/qquicklistview_p.h @@ -146,7 +146,7 @@ public: QQuickViewSection *sectionCriteria(); QString currentSection() const; - void setHighlightFollowsCurrentItem(bool) Q_DECL_OVERRIDE; + void setHighlightFollowsCurrentItem(bool) override; qreal highlightMoveVelocity() const; void setHighlightMoveVelocity(qreal); @@ -157,7 +157,7 @@ public: int highlightResizeDuration() const; void setHighlightResizeDuration(int); - void setHighlightMoveDuration(int) Q_DECL_OVERRIDE; + void setHighlightMoveDuration(int) override; enum SnapMode { NoSnap, SnapToItem, SnapOneItem }; Q_ENUM(SnapMode) @@ -192,12 +192,12 @@ Q_SIGNALS: Q_REVISION(2) void footerPositioningChanged(); protected: - void viewportMoved(Qt::Orientations orient) Q_DECL_OVERRIDE; - void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE; - void geometryChanged(const QRectF &newGeometry,const QRectF &oldGeometry) Q_DECL_OVERRIDE; - void initItem(int index, QObject *item) Q_DECL_OVERRIDE; - qreal maxYExtent() const Q_DECL_OVERRIDE; - qreal maxXExtent() const Q_DECL_OVERRIDE; + void viewportMoved(Qt::Orientations orient) override; + void keyPressEvent(QKeyEvent *) override; + void geometryChanged(const QRectF &newGeometry,const QRectF &oldGeometry) override; + void initItem(int index, QObject *item) override; + qreal maxYExtent() const override; + qreal maxXExtent() const override; }; class QQuickListViewAttached : public QQuickItemViewAttached diff --git a/src/quick/items/qquickpathview_p.h b/src/quick/items/qquickpathview_p.h index 669ef60ef7..0e237b7b74 100644 --- a/src/quick/items/qquickpathview_p.h +++ b/src/quick/items/qquickpathview_p.h @@ -221,14 +221,14 @@ Q_SIGNALS: void cacheItemCountChanged(); protected: - void updatePolish() Q_DECL_OVERRIDE; - void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; - void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; - void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE; + void updatePolish() override; + void mousePressEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *) override; bool sendMouseEvent(QMouseEvent *event); - bool childMouseEventFilter(QQuickItem *, QEvent *) Q_DECL_OVERRIDE; - void mouseUngrabEvent() Q_DECL_OVERRIDE; - void componentComplete() Q_DECL_OVERRIDE; + bool childMouseEventFilter(QQuickItem *, QEvent *) override; + void mouseUngrabEvent() override; + void componentComplete() override; private Q_SLOTS: void refill(); diff --git a/src/quick/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h index 082f427f2c..d58c986d1a 100644 --- a/src/quick/items/qquickpathview_p_p.h +++ b/src/quick/items/qquickpathview_p_p.h @@ -80,7 +80,7 @@ public: void init(); - void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) Q_DECL_OVERRIDE { + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) override { if (change.sizeChange() && (!highlightItem || item != highlightItem)) { if (QQuickPathViewAttached *att = attached(item)) att->m_percent = -1; diff --git a/src/quick/items/qquickview.h b/src/quick/items/qquickview.h index 1fcc34e3a1..6d3b30e4c4 100644 --- a/src/quick/items/qquickview.h +++ b/src/quick/items/qquickview.h @@ -97,14 +97,14 @@ private Q_SLOTS: void continueExecute(); protected: - void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE; - void timerEvent(QTimerEvent*) Q_DECL_OVERRIDE; - - void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE; - void keyReleaseEvent(QKeyEvent *) Q_DECL_OVERRIDE; - void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE; - void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE; - void mouseMoveEvent(QMouseEvent *) Q_DECL_OVERRIDE; + void resizeEvent(QResizeEvent *) override; + void timerEvent(QTimerEvent*) override; + + void keyPressEvent(QKeyEvent *) override; + void keyReleaseEvent(QKeyEvent *) override; + void mousePressEvent(QMouseEvent *) override; + void mouseReleaseEvent(QMouseEvent *) override; + void mouseMoveEvent(QMouseEvent *) override; private: Q_DISABLE_COPY(QQuickView) Q_DECLARE_PRIVATE(QQuickView) diff --git a/src/quick/items/qquickview_p.h b/src/quick/items/qquickview_p.h index a090bdc9f7..f92d4b95d6 100644 --- a/src/quick/items/qquickview_p.h +++ b/src/quick/items/qquickview_p.h @@ -88,7 +88,7 @@ public: ~QQuickViewPrivate(); void execute(); - void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) Q_DECL_OVERRIDE; + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) override; void initResize(); void updateSize(); void setRootObject(QObject *); -- cgit v1.2.3 From d7cd210bb4aed802d30e6f67e2db950e561a033b Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 18 Jan 2017 12:06:57 +0100 Subject: Make inspector animation speed test more robust We don't exactly know when the animation speed is actually set and the system clock may play tricks on us. Consider the test failed when the wrong animation speed is witnessed 3 times in a row and successful if the correct one is witnessed 3 times in a row. Also, make sure we don't confuse lines from different hits of the timer. Task-number: QTBUG-58186 Change-Id: Iaa2c35f723a92f32131e36084399b3d32accb7d0 Reviewed-by: Robin Burchell --- .../qml/debugger/qqmlinspector/data/qtquick2.qml | 5 +- .../debugger/qqmlinspector/tst_qqmlinspector.cpp | 53 ++++++++++++++-------- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/tests/auto/qml/debugger/qqmlinspector/data/qtquick2.qml b/tests/auto/qml/debugger/qqmlinspector/data/qtquick2.qml index f44c653840..f43cff15e4 100644 --- a/tests/auto/qml/debugger/qqmlinspector/data/qtquick2.qml +++ b/tests/auto/qml/debugger/qqmlinspector/data/qtquick2.qml @@ -29,16 +29,15 @@ Rectangle { } var milliDelta = millis - prevHit; - if (milliDelta < 0) + if (milliDelta <= 0) milliDelta += 1000; - console.log(milliDelta, "milliseconds "); prevHit = millis; var delta = parent.rotation - prevRotation; if (delta < 0) delta += 360 prevRotation = parent.rotation - console.log(delta, "degrees "); + console.log(milliDelta, delta, "ms/degrees "); } } } diff --git a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp index f55fef232e..9461922eff 100644 --- a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp +++ b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp @@ -102,29 +102,46 @@ void tst_QQmlInspector::startQmlProcess(const QString &qmlFile, bool restrictSer void tst_QQmlInspector::checkAnimationSpeed(int targetMillisPerDegree) { - QString degreesString = QStringLiteral("degrees"); - QString millisecondsString = QStringLiteral("milliseconds"); - for (int i = 0; i < 2; ++i) { // skip one period; the change might have happened inside it - int position = m_process->output().length(); - while (!m_process->output().mid(position).contains(degreesString) || - !m_process->output().mid(position).contains(millisecondsString)) { + const QString markerString = QStringLiteral("ms/degrees"); + + // Funny things can happen with time and VMs. Also the change might take a while to propagate. + // Thus, we wait until we either have 3 passes or 3 failures in a row, or 10 loops have passed. + + int numFailures = 0; + int numPasses = 0; + + for (int i = 0; i < 10; ++i) { + QString output = m_process->output(); + int position = output.length(); + do { QVERIFY(QQmlDebugTest::waitForSignal(m_process.data(), SIGNAL(readyReadStandardOutput()))); + output = m_process->output(); + } while (!output.mid(position).contains(markerString)); + + + QStringList words = output.split(QLatin1Char(' ')); + const int marker = words.lastIndexOf(markerString); + QVERIFY(marker > 1); + const double degrees = words[marker - 1].toDouble(); + const int milliseconds = words[marker - 2].toInt(); + const double millisecondsPerDegree = milliseconds / degrees; + + if (millisecondsPerDegree > targetMillisPerDegree - 3 + || millisecondsPerDegree < targetMillisPerDegree + 3) { + if (++numPasses == 3) + return; // pass + numFailures = 0; + } else { + QVERIFY2(++numFailures < 3, + QString("3 consecutive failures when checking for %1 milliseconds per degree") + .arg(targetMillisPerDegree).toLocal8Bit().constData()); + numPasses = 0; } } - QStringList words = m_process->output().split(QLatin1Char(' ')); - int degreesMarker = words.lastIndexOf(degreesString); - QVERIFY(degreesMarker > 1); - double degrees = words[degreesMarker - 1].toDouble(); - int millisecondsMarker = words.lastIndexOf(millisecondsString); - QVERIFY(millisecondsMarker > 1); - int milliseconds = words[millisecondsMarker - 1].toInt(); - - double millisecondsPerDegree = milliseconds / degrees; - QVERIFY(millisecondsPerDegree > targetMillisPerDegree - 3); - QVERIFY(millisecondsPerDegree < targetMillisPerDegree + 3); - + QFAIL(QString("Animation speed won't settle to %1 milliseconds per degree") + .arg(targetMillisPerDegree).toLocal8Bit().constData()); } void tst_QQmlInspector::cleanup() -- cgit v1.2.3 From 2e7b1e0e8e606f1e35d666dd80f512b3c37d2c6a Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 18 Jan 2017 02:22:39 +0100 Subject: QQmlListModel: Fix potential uninitialized value If roleCount is 0, alloca(0) will give us a pointer. The loop will then not initialize the returned pointer (due to the roleCount being 0), passing an uninitialized changedRoles to emitDirectNotifies. emitDirectNotifies doesn't access changedRoles unconditionally (via another for loop), but this is probably better to check than not. Coverity-Id: 172868 Done-with: John Brooks Change-Id: I821c06221d2659d3310082b4e81442cc58b197f7 Reviewed-by: Simon Hausmann --- src/qml/types/qqmllistmodel.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index 5e06455b26..cc4ccbaeb1 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -1267,10 +1267,12 @@ void ModelNodeMetaObject::updateValues() { const int roleCount = m_model->m_listModel->roleCount(); if (!m_initialized) { - int *changedRoles = reinterpret_cast(alloca(roleCount * sizeof(int))); - for (int i = 0; i < roleCount; ++i) - changedRoles[i] = i; - emitDirectNotifies(changedRoles, roleCount); + if (roleCount) { + int *changedRoles = reinterpret_cast(alloca(roleCount * sizeof(int))); + for (int i = 0; i < roleCount; ++i) + changedRoles[i] = i; + emitDirectNotifies(changedRoles, roleCount); + } return; } for (int i=0 ; i < roleCount ; ++i) { -- cgit v1.2.3 From 1d6bdb6ba00a317700ac734b7862983e23c5a842 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 18 Jan 2017 01:49:35 +0100 Subject: qmltime: Reject 0 iterations Causes a divide-by-zero. Low risk, but let's fix it anyway. Coverity-Id: 161333 Change-Id: I7631abdca469a5dd9e2becf32cc9aa4f5cf515dc Reviewed-by: Simon Hausmann --- tools/qmltime/qmltime.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qmltime/qmltime.cpp b/tools/qmltime/qmltime.cpp index 4c282dd8f4..b337ccac5c 100644 --- a/tools/qmltime/qmltime.cpp +++ b/tools/qmltime/qmltime.cpp @@ -222,7 +222,7 @@ int main(int argc, char ** argv) QByteArray its(argv[ii]); bool ok = false; iterations = its.toUInt(&ok); - if (!ok) + if (!ok || iterations == 0) usage(argv[0]); } else { usage(argv[0]); -- cgit v1.2.3 From 7a8842460dc3c5e4e4ed42e7e2ae5bc619be5c78 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 5 Jan 2017 16:52:54 +0100 Subject: Q_ENUMS -> Q_ENUM and Q_FLAGS -> Q_FLAG Change-Id: Ibedd0d0c23cf194ea02a229ab643450dbefd40aa Reviewed-by: Shawn Rutledge --- src/imports/layouts/qquicklinearlayout_p.h | 2 +- src/imports/xmllistmodel/qqmlxmllistmodel_p.h | 2 +- src/quick/items/qquickflickable_p.h | 3 +-- tests/auto/quick/qquickxmllistmodel/qquickxmllistmodel.pro | 4 +++- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/imports/layouts/qquicklinearlayout_p.h b/src/imports/layouts/qquicklinearlayout_p.h index b425df0fa4..f796c8a855 100644 --- a/src/imports/layouts/qquicklinearlayout_p.h +++ b/src/imports/layouts/qquicklinearlayout_p.h @@ -152,8 +152,8 @@ public: int rows() const; void setRows(int rows); - Q_ENUMS(Flow) enum Flow { LeftToRight, TopToBottom }; + Q_ENUM(Flow) Flow flow() const; void setFlow(Flow flow); diff --git a/src/imports/xmllistmodel/qqmlxmllistmodel_p.h b/src/imports/xmllistmodel/qqmlxmllistmodel_p.h index 6605ce9aa6..e6a0898bb9 100644 --- a/src/imports/xmllistmodel/qqmlxmllistmodel_p.h +++ b/src/imports/xmllistmodel/qqmlxmllistmodel_p.h @@ -79,7 +79,6 @@ class QQuickXmlListModel : public QAbstractListModel, public QQmlParserStatus { Q_OBJECT Q_INTERFACES(QQmlParserStatus) - Q_ENUMS(Status) Q_PROPERTY(Status status READ status NOTIFY statusChanged) Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged) @@ -119,6 +118,7 @@ public: Q_INVOKABLE QQmlV4Handle get(int index) const; enum Status { Null, Ready, Loading, Error }; + Q_ENUM(Status) Status status() const; qreal progress() const; diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h index 78c8271525..52cade1472 100644 --- a/src/quick/items/qquickflickable_p.h +++ b/src/quick/items/qquickflickable_p.h @@ -113,8 +113,6 @@ class Q_QUICK_PRIVATE_EXPORT QQuickFlickable : public QQuickItem Q_PROPERTY(QQmlListProperty flickableChildren READ flickableChildren) Q_CLASSINFO("DefaultProperty", "flickableData") - Q_FLAGS(BoundsBehavior) - public: QQuickFlickable(QQuickItem *parent=0); ~QQuickFlickable(); @@ -129,6 +127,7 @@ public: DragAndOvershootBounds = DragOverBounds | OvershootBounds }; Q_DECLARE_FLAGS(BoundsBehavior, BoundsBehaviorFlag) + Q_FLAG(BoundsBehavior) BoundsBehavior boundsBehavior() const; void setBoundsBehavior(BoundsBehavior); diff --git a/tests/auto/quick/qquickxmllistmodel/qquickxmllistmodel.pro b/tests/auto/quick/qquickxmllistmodel/qquickxmllistmodel.pro index 642345a4bb..902325802c 100644 --- a/tests/auto/quick/qquickxmllistmodel/qquickxmllistmodel.pro +++ b/tests/auto/quick/qquickxmllistmodel/qquickxmllistmodel.pro @@ -2,7 +2,9 @@ CONFIG += testcase TARGET = tst_qquickxmllistmodel macx:CONFIG -= app_bundle -SOURCES += tst_qquickxmllistmodel.cpp +SOURCES += tst_qquickxmllistmodel.cpp \ + ../../../../src/imports/xmllistmodel/qqmlxmllistmodel.cpp +HEADERS += ../../../../src/imports/xmllistmodel/qqmlxmllistmodel_p.h include (../../shared/util.pri) -- cgit v1.2.3 From 94324a4ea2261940d1d55dec141c885bf4f57832 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 19 Jan 2017 09:05:46 +0100 Subject: Fix memory leak in V4 Transitions contain both an id and a set of flags, but the sorting failed to take the flags into account in the operator<. As a result we would some times end up with duplicate entries if the same id was added multiple times with different flags. If the same id was added again and again with varying flags, this could lead to an ever expanding list filled with duplicate entries. Fix this by also taking flags into account in operator< so that operator< and operator== are symetric and the list gets correctly sorted. Change-Id: I762ec3f0c5b4ed9a1aecb9a883187a0445491591 Reviewed-by: Simon Hausmann Reviewed-by: Robin Burchell --- src/qml/jsruntime/qv4internalclass_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h index dcda949c97..1d8ef4b0fb 100644 --- a/src/qml/jsruntime/qv4internalclass_p.h +++ b/src/qml/jsruntime/qv4internalclass_p.h @@ -234,7 +234,7 @@ struct InternalClassTransition { return id == other.id && flags == other.flags; } bool operator<(const InternalClassTransition &other) const - { return id < other.id; } + { return id < other.id || (id == other.id && flags < other.flags); } }; struct InternalClass : public QQmlJS::Managed { -- cgit v1.2.3 From f6cc3c9a73765717c3e296ca97f17ba685f8baf4 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 23 Nov 2016 13:50:16 +0100 Subject: Remove support for WinRT 8.1 and Windows Phone 8.1 Task-number: QTBUG-57288 Change-Id: Id106f09dc824fbd95780dc5b479e16802d183e57 Reviewed-by: Simon Hausmann --- src/3rdparty/masm/stubs/ExecutableAllocator.h | 13 ++----------- src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp | 11 ----------- src/qml/compiler/qv4compilationunitmapper_win.cpp | 8 -------- src/qml/qml/qqmlengine.cpp | 1 - src/qml/qml/qqmlplatform.cpp | 2 -- 5 files changed, 2 insertions(+), 33 deletions(-) diff --git a/src/3rdparty/masm/stubs/ExecutableAllocator.h b/src/3rdparty/masm/stubs/ExecutableAllocator.h index 5a3939b7b2..8617229b06 100644 --- a/src/3rdparty/masm/stubs/ExecutableAllocator.h +++ b/src/3rdparty/masm/stubs/ExecutableAllocator.h @@ -39,11 +39,6 @@ #ifndef MASM_EXECUTABLEALLOCATOR_H #define MASM_EXECUTABLEALLOCATOR_H -// Defined via mkspec -#if _MSC_VER >= 1900 -#include -#endif - #include #include #include @@ -117,13 +112,11 @@ struct ExecutableAllocator { DWORD oldProtect; # if !OS(WINRT) VirtualProtect(addr, size, PAGE_READWRITE, &oldProtect); -# elif _MSC_VER >= 1900 +# else bool hr = VirtualProtectFromApp(addr, size, PAGE_READWRITE, &oldProtect); if (!hr) { Q_UNREACHABLE(); } -# else - (void)oldProtect; # endif # else int mode = PROT_READ | PROT_WRITE; @@ -152,13 +145,11 @@ struct ExecutableAllocator { DWORD oldProtect; # if !OS(WINRT) VirtualProtect(addr, size, PAGE_EXECUTE_READ, &oldProtect); -# elif _MSC_VER >= 1900 +# else bool hr = VirtualProtectFromApp(addr, size, PAGE_EXECUTE_READ, &oldProtect); if (!hr) { Q_UNREACHABLE(); } -# else - (void)oldProtect; # endif # else int mode = PROT_READ | PROT_EXEC; diff --git a/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp b/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp index b7ad723f07..0a6eda8b98 100644 --- a/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp +++ b/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp @@ -32,19 +32,8 @@ #include "windows.h" #include -#if _MSC_VER >= 1900 // Try to use JIT by default and fallback to non-JIT on first error static bool qt_winrt_use_jit = true; -#else // _MSC_VER < 1900 -# define PAGE_EXECUTE 0x10 -# define PAGE_EXECUTE_READ 0x20 -# define PAGE_EXECUTE_READWRITE 0x40 -# define MEM_RELEASE 0x8000 -inline void* VirtualAllocFromApp(void*, size_t, int, int) { return 0; } -inline bool VirtualProtectFromApp(void *, size_t, int, DWORD*) { return false; } -inline bool VirtualFree(void *, size_t, DWORD) { return false; } -static bool qt_winrt_use_jit = false; -#endif // _MSC_VER < 1900 namespace WTF { diff --git a/src/qml/compiler/qv4compilationunitmapper_win.cpp b/src/qml/compiler/qv4compilationunitmapper_win.cpp index 457b702ac3..37cac846a0 100644 --- a/src/qml/compiler/qv4compilationunitmapper_win.cpp +++ b/src/qml/compiler/qv4compilationunitmapper_win.cpp @@ -75,7 +75,6 @@ CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, co CloseHandle(handle); }); -#if !defined(Q_OS_WINRT) || _MSC_VER >= 1900 CompiledData::Unit header; DWORD bytesRead; if (!ReadFile(handle, reinterpret_cast(&header), sizeof(header), &bytesRead, nullptr)) { @@ -115,19 +114,12 @@ CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, co } return reinterpret_cast(dataPtr); -#else - Q_UNUSED(sourcePath); - *errorString = QStringLiteral("Compilation unit mapping not supported on WinRT 8.1"); - return nullptr; -#endif } void CompilationUnitMapper::close() { -#if !defined(Q_OS_WINRT) || _MSC_VER >= 1900 if (dataPtr != nullptr) UnmapViewOfFile(dataPtr); -#endif dataPtr = nullptr; } diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index f59b9136a3..e1fa97b52f 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -443,7 +443,6 @@ The following functions are also on the Qt object. \li \c "unix" - Other Unix-based OS \li \c "windows" - Windows \li \c "winrt" - WinRT / UWP - \li \c "winphone" - Windows Phone \endlist \endtable */ diff --git a/src/qml/qml/qqmlplatform.cpp b/src/qml/qml/qqmlplatform.cpp index bef79a5ad0..64ca208f1b 100644 --- a/src/qml/qml/qqmlplatform.cpp +++ b/src/qml/qml/qqmlplatform.cpp @@ -65,8 +65,6 @@ QString QQmlPlatform::os() return QStringLiteral("tvos"); #elif defined(Q_OS_MAC) return QStringLiteral("osx"); -#elif defined(Q_OS_WINPHONE) - return QStringLiteral("winphone"); #elif defined(Q_OS_WINRT) return QStringLiteral("winrt"); #elif defined(Q_OS_WIN) -- cgit v1.2.3 From edffdcf9b45641708fb242449b77e8e53ee05d87 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 18 Jan 2017 20:08:44 +0100 Subject: test262: Allow specifying a custom V4CMD Useful for running a test tree against different qmljs or if qmljs is outside PATH. Change-Id: Ibaa24a15d32b21f9293db2c042fe3f1de3bb75eb Reviewed-by: Simon Hausmann --- tests/manual/v4/tests.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/manual/v4/tests.pro b/tests/manual/v4/tests.pro index a86a6bf6af..ce4a34f7a0 100644 --- a/tests/manual/v4/tests.pro +++ b/tests/manual/v4/tests.pro @@ -1,7 +1,7 @@ TEMPLATE = aux TESTSCRIPT=$$PWD/test262.py -V4CMD = qmljs +isEmpty(V4CMD): V4CMD = qmljs checktarget.target = check checktarget.commands = python $$TESTSCRIPT --command=$$V4CMD --parallel --with-test-expectations --update-expectations -- cgit v1.2.3 From 03505d6eb7164298617c1a88979e802d7da12e15 Mon Sep 17 00:00:00 2001 From: Oleg Yadrov Date: Tue, 3 Jan 2017 14:49:13 -0800 Subject: StackLayout: propagate rearrange() call to child layouts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-57867 Change-Id: I0190b892e2bc2966b82a0dbd99e53fd9d6848957 Reviewed-by: Jan Arve Sæther --- src/imports/layouts/qquickstacklayout.cpp | 6 +- .../quick/qquicklayouts/data/tst_stacklayout.qml | 107 +++++++++++++++++++++ tests/auto/quick/qquicklayouts/qquicklayouts.pro | 3 +- 3 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml diff --git a/src/imports/layouts/qquickstacklayout.cpp b/src/imports/layouts/qquickstacklayout.cpp index a223dd0374..0bfe63816d 100644 --- a/src/imports/layouts/qquickstacklayout.cpp +++ b/src/imports/layouts/qquickstacklayout.cpp @@ -307,7 +307,11 @@ void QQuickStackLayout::rearrange(const QSizeF &newSize) QQuickItem *item = itemAt(d->currentIndex); Q_ASSERT(item); item->setPosition(QPointF(0,0)); // ### respect alignment? - item->setSize(newSize.expandedTo(hints.min()).boundedTo(hints.max())); + const QSizeF oldSize(item->width(), item->height()); + const QSizeF effectiveNewSize = newSize.expandedTo(hints.min()).boundedTo(hints.max()); + item->setSize(effectiveNewSize); + if (effectiveNewSize == oldSize) + item->polish(); QQuickLayout::rearrange(newSize); } diff --git a/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml b/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml new file mode 100644 index 0000000000..8234ac6ef7 --- /dev/null +++ b/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtTest 1.0 +import QtQuick.Layouts 1.3 + +Item { + id: container + width: 200 + height: 200 + TestCase { + id: testCase + name: "Tests_StackLayout" + when: windowShown + width: 200 + height: 200 + + Component { + id: layout_rearrange_Component + + StackLayout { + width: 640 + height: 480 + + property alias testRectangle: testRectangle + + RowLayout { + spacing: 0 + + Rectangle { + Layout.preferredWidth: 100 + Layout.preferredHeight: 100 + } + + Rectangle { + id: testRectangle + Layout.preferredWidth: 100 + Layout.preferredHeight: 100 + visible: false + } + + Item { + Layout.fillWidth: true + } + } + } + } + + function test_rearrange() + { + var layout = layout_rearrange_Component.createObject(container) + compare(layout.testRectangle.x, 0) + layout.testRectangle.visible = true + tryCompare(layout.testRectangle, "x", 100) + + layout.destroy() + } + } +} diff --git a/tests/auto/quick/qquicklayouts/qquicklayouts.pro b/tests/auto/quick/qquicklayouts/qquicklayouts.pro index 9ed3e076be..5079d0a182 100644 --- a/tests/auto/quick/qquicklayouts/qquicklayouts.pro +++ b/tests/auto/quick/qquicklayouts/qquicklayouts.pro @@ -9,5 +9,6 @@ TESTDATA = data/* OTHER_FILES += \ data/tst_rowlayout.qml \ - data/tst_gridlayout.qml + data/tst_gridlayout.qml \ + data/tst_stacklayout.qml -- cgit v1.2.3 From 7ee15ecdd960cde6d0202e9675f7f6bd31bbb927 Mon Sep 17 00:00:00 2001 From: Oleg Yadrov Date: Mon, 19 Dec 2016 12:08:20 -0800 Subject: PathAnimation: fix bug when PathSvg or PathLine is the last item in Path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both QQuickPathLine and QQuickPathSvg inherit QQuickCurve class which has “x” and “y” properties that return qreal type, but internally they are stored as QQmlNullableValue. At the same time, if any of them is not specified explicitly, its getter returns 0. QQuickPath processes QQuickPath%Type% objects and produces a QPainterPath which later used by QQuickPathAnimation. QQuickPathAnimation only created a QAbstractAnimationJob if QQuickPath::hasEnd returned true, and hasEnd returned true only if both “x” and “y” were specified explicitly. All that in conjunction led to the situation when if you had either - a PathLine with unspecified “x” or “y”; or - a PathSvg which was the last (or the only) path element in your Path, PathAnimation would not start. This patch removes hasEnd check, it should be safe to do because QPainterPath is always valid anyway due to the fact QQuickCurve::x() and QQuickCurve::y() return 0 if they have not been not explicitly set. Task-number: QTBUG-57666 Change-Id: Id320aaeb5aff0964d6493b7b80d5d9a7d36acce8 Reviewed-by: Robin Burchell --- src/quick/items/qquickitemanimation.cpp | 2 +- src/quick/util/qquickpath.cpp | 14 ------- src/quick/util/qquickpath_p.h | 1 - .../data/pathLineUnspecifiedXYBug.qml | 28 ++++++++++++++ .../qquickanimations/data/pathSvgAnimation.qml | 25 ++++++++++++ .../qquickanimations/tst_qquickanimations.cpp | 44 ++++++++++++++++++++++ 6 files changed, 98 insertions(+), 16 deletions(-) create mode 100644 tests/auto/quick/qquickanimations/data/pathLineUnspecifiedXYBug.qml create mode 100644 tests/auto/quick/qquickanimations/data/pathSvgAnimation.qml diff --git a/src/quick/items/qquickitemanimation.cpp b/src/quick/items/qquickitemanimation.cpp index b33705e75e..9873622f41 100644 --- a/src/quick/items/qquickitemanimation.cpp +++ b/src/quick/items/qquickitemanimation.cpp @@ -869,7 +869,7 @@ QAbstractAnimationJob* QQuickPathAnimation::transition(QQuickStateActions &actio data->reverse = direction == Backward ? true : false; data->fromSourced = false; data->fromDefined = (d->path && d->path->hasStartX() && d->path->hasStartY()) ? true : false; - data->toDefined = d->path ? d->path->hasEnd() : false; + data->toDefined = d->path ? true : false; int origModifiedSize = modified.count(); for (int i = 0; i < actions.count(); ++i) { diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp index 25a4433a9b..e31aed7b6d 100644 --- a/src/quick/util/qquickpath.cpp +++ b/src/quick/util/qquickpath.cpp @@ -149,20 +149,6 @@ bool QQuickPath::isClosed() const return d->closed; } -bool QQuickPath::hasEnd() const -{ - Q_D(const QQuickPath); - for (int i = d->_pathElements.count() - 1; i > -1; --i) { - if (QQuickCurve *curve = qobject_cast(d->_pathElements.at(i))) { - if ((!curve->hasX() && !curve->hasRelativeX()) || (!curve->hasY() && !curve->hasRelativeY())) - return false; - else - return true; - } - } - return hasStartX() && hasStartY(); -} - /*! \qmlproperty list QtQuick::Path::pathElements This property holds the objects composing the path. diff --git a/src/quick/util/qquickpath_p.h b/src/quick/util/qquickpath_p.h index 06ad389b49..c0a96cad4f 100644 --- a/src/quick/util/qquickpath_p.h +++ b/src/quick/util/qquickpath_p.h @@ -390,7 +390,6 @@ public: bool hasStartY() const; bool isClosed() const; - bool hasEnd() const; QPainterPath path() const; QStringList attributes() const; diff --git a/tests/auto/quick/qquickanimations/data/pathLineUnspecifiedXYBug.qml b/tests/auto/quick/qquickanimations/data/pathLineUnspecifiedXYBug.qml new file mode 100644 index 0000000000..426360bbcc --- /dev/null +++ b/tests/auto/quick/qquickanimations/data/pathLineUnspecifiedXYBug.qml @@ -0,0 +1,28 @@ +import QtQuick 2.0 + +Rectangle { + width: 400 + height: 400 + + Rectangle { + id: redRect + color: "red" + width: 100; height: 100 + x: 50; y: 50 + } + + PathAnimation { + target: redRect + duration: 1000 + path: Path { + startX: 100; startY: 100 + + PathLine { + x: 200 + y: 200 + } + + PathLine {} + } + } +} diff --git a/tests/auto/quick/qquickanimations/data/pathSvgAnimation.qml b/tests/auto/quick/qquickanimations/data/pathSvgAnimation.qml new file mode 100644 index 0000000000..e409bb031f --- /dev/null +++ b/tests/auto/quick/qquickanimations/data/pathSvgAnimation.qml @@ -0,0 +1,25 @@ +import QtQuick 2.0 + +Rectangle { + width: 400 + height: 400 + + Rectangle { + id: redRect + color: "red" + width: 100; height: 100 + x: 50; y: 50 + } + + PathAnimation { + target: redRect + duration: 1000; + path: Path { + startX: 100; startY: 100 + + PathSvg { + path: "M 200 200" + } + } + } +} diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp index 6e265503a1..fbd6c9c97e 100644 --- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp +++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp @@ -101,6 +101,8 @@ private slots: void scriptActionCrash(); void animatorInvalidTargetCrash(); void defaultPropertyWarning(); + void pathSvgAnimation(); + void pathLineUnspecifiedXYBug(); }; #define QTIMED_COMPARE(lhs, rhs) do { \ @@ -1523,6 +1525,48 @@ void tst_qquickanimations::defaultPropertyWarning() QVERIFY(warnings.isEmpty()); } +// QTBUG-57666 +void tst_qquickanimations::pathSvgAnimation() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("pathSvgAnimation.qml")); + QScopedPointer rect(qobject_cast(component.create())); + QVERIFY(rect); + + QQuickRectangle *redRect = rect->findChild(); + QVERIFY(redRect); + QQuickPathAnimation *pathAnim = rect->findChild(); + QVERIFY(pathAnim); + + QCOMPARE(redRect->x(), qreal(50)); + QCOMPARE(redRect->y(), qreal(50)); + + pathAnim->start(); + QTRY_COMPARE(redRect->x(), qreal(200)); + QCOMPARE(redRect->y(), qreal(200)); +} + +// QTBUG-57666 +void tst_qquickanimations::pathLineUnspecifiedXYBug() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("pathLineUnspecifiedXYBug.qml")); + QScopedPointer rect(qobject_cast(component.create())); + QVERIFY(rect); + + QQuickRectangle *redRect = rect->findChild(); + QVERIFY(redRect); + QQuickPathAnimation *pathAnim = rect->findChild(); + QVERIFY(pathAnim); + + QCOMPARE(redRect->x(), qreal(50)); + QCOMPARE(redRect->y(), qreal(50)); + + pathAnim->start(); + QTRY_COMPARE(redRect->x(), qreal(0)); + QCOMPARE(redRect->y(), qreal(0)); +} + QTEST_MAIN(tst_qquickanimations) #include "tst_qquickanimations.moc" -- cgit v1.2.3 From 0b1d4983ff523be4c5758fc36e407fa7a4a18158 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Fri, 20 Jan 2017 10:21:01 +0100 Subject: qmltest: added layout/tst_layout.qml and related files They are moved from qtquickcontrols:tests/auto/controls in 3437fd56. Task-number: QTBUG-58294 Change-Id: I281d4e505b2f699154dd4efb7a4601bdf3856295 Reviewed-by: Shawn Rutledge --- tests/auto/qmltest/layout/Container.qml | 55 ++++++++++++++++++++ tests/auto/qmltest/layout/ContainerUser.qml | 53 ++++++++++++++++++++ tests/auto/qmltest/layout/tst_layout.qml | 78 +++++++++++++++++++++++++++++ 3 files changed, 186 insertions(+) create mode 100644 tests/auto/qmltest/layout/Container.qml create mode 100644 tests/auto/qmltest/layout/ContainerUser.qml create mode 100644 tests/auto/qmltest/layout/tst_layout.qml diff --git a/tests/auto/qmltest/layout/Container.qml b/tests/auto/qmltest/layout/Container.qml new file mode 100644 index 0000000000..db3d68c485 --- /dev/null +++ b/tests/auto/qmltest/layout/Container.qml @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Layouts 1.2 + +Item { + objectName: "qtbug51927-window" + visible: true + + default property alias _contents: customContent.data + + ColumnLayout { + id: customContent + objectName: "qtbug51927-columnLayout" + anchors.fill: parent + } +} diff --git a/tests/auto/qmltest/layout/ContainerUser.qml b/tests/auto/qmltest/layout/ContainerUser.qml new file mode 100644 index 0000000000..ff7ce6221b --- /dev/null +++ b/tests/auto/qmltest/layout/ContainerUser.qml @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.6 +import QtQuick.Window 2.2 + +Container { + visible: true + + Text { + objectName: "qtbug51927-text" + text: qsTr("Hello World") + anchors.centerIn: parent + renderType: Text.QtRendering + } +} diff --git a/tests/auto/qmltest/layout/tst_layout.qml b/tests/auto/qmltest/layout/tst_layout.qml new file mode 100644 index 0000000000..ee44a01080 --- /dev/null +++ b/tests/auto/qmltest/layout/tst_layout.qml @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtTest 1.0 + +TestCase { + id: testCase + name: "Tests_Layout" + when:windowShown + width:400 + height:400 + + function test_invalidParent() { + ignoreWarning(':1:49: QML QtObject: Layout must be attached to Item elements') + var object = Qt.createQmlObject('import QtQuick 2.2; import QtQuick.Layouts 1.0; QtObject { Layout.fillWidth: true }', testCase, ''); + object.destroy() + } + + function test_defaultPropertyAliasCrash() { + var containerUserComponent = Qt.createComponent("ContainerUser.qml"); + compare(containerUserComponent.status, Component.Ready); + + var containerUser = containerUserComponent.createObject(testCase); + verify(containerUser); + + // Shouldn't crash. + containerUser.destroy(); + } +} + -- cgit v1.2.3 From b3629b4c27a17e7fbb2f3098b17d9b449f64bc47 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Fri, 20 Jan 2017 00:36:57 +0100 Subject: tst_qqmlecmascript: Add some simple coverage for instanceof Since I'm working on this, it is nice to have some simple verification that things are working. I don't expect this to provide full coverage, but it should at least make sure that the basics are ok, and nicely provides a place to put further tests if it ever somehow breaks. Change-Id: If91154dee836cc514515bde122e48b271de22676 Reviewed-by: Lars Knoll --- .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 64 ++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index b8f12e772d..8c0b0601fc 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -331,6 +331,8 @@ private slots: void qtbug_54589(); void qtbug_54687(); void stringify_qtbug_50592(); + void instanceof_data(); + void instanceof(); private: // static void propertyVarWeakRefCallback(v8::Persistent object, void* parameter); @@ -8114,6 +8116,68 @@ void tst_qqmlecmascript::stringify_qtbug_50592() QCOMPARE(obj->property("source").toString(), QString::fromLatin1("http://example.org/some_nonexistant_image.png")); } +void tst_qqmlecmascript::instanceof_data() +{ + QTest::addColumn("setupCode"); + QTest::addColumn("expectedValue"); + + // so the way this works is that the name of the test tag defines the test + // to run. the code in setupCode defines code run before the actual test + // (e.g. to create vars). + // + // the expectedValue is either a boolean true or false for whether the two + // operands are indeed an instanceof each other, or a string for the + // expected error message. + QTest::newRow("String instanceof String") + << "" + << QVariant(false); + QTest::newRow("s instanceof String") + << "var s = \"hello\"" + << QVariant(false); + QTest::newRow("objectString instanceof String") + << "var objectString = new String(\"hello\")" + << QVariant(true); + QTest::newRow("o instanceof Object") + << "var o = new Object()" + << QVariant(true); + QTest::newRow("o instanceof String") + << "var o = new Object()" + << QVariant(false); + QTest::newRow("true instanceof true") + << "" + << QVariant("TypeError: Type error"); + QTest::newRow("1 instanceof Math") + << "" + << QVariant("TypeError: Type error"); + QTest::newRow("date instanceof Date") + << "var date = new Date" + << QVariant(true); + QTest::newRow("date instanceof Object") + << "var date = new Date" + << QVariant(true); + QTest::newRow("date instanceof String") + << "var date = new Date" + << QVariant(false); +} + +void tst_qqmlecmascript::instanceof() +{ + QFETCH(QString, setupCode); + QFETCH(QVariant, expectedValue); + + QJSEngine engine; + QJSValue ret = engine.evaluate(setupCode + ";\n" + QTest::currentDataTag()); + + if (expectedValue.type() == QMetaType::Bool) { + bool returnValue = ret.toBool(); + QVERIFY2(!ret.isError(), qPrintable(ret.toString())); + QCOMPARE(returnValue, expectedValue.toBool()); + } else { + QVERIFY2(ret.isError(), qPrintable(ret.toString())); + QCOMPARE(ret.toString(), expectedValue.toString()); + } +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" -- cgit v1.2.3 From ce736406cde2edc2315ed58c27f6cd6482bedc65 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 22 Dec 2016 12:51:24 +0100 Subject: Check pointers for 0 before calling mark on them Fix the one place where we marked a Pointer without checking whether it is 0 first. Change-Id: I93ad0d9bc2d49594f3759ca429fd15615a16565f Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4regexpobject.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 218695624b..41d8010fef 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -307,7 +307,8 @@ void RegExpCtor::markObjects(Heap::Base *that, ExecutionEngine *e) { RegExpCtor::Data *This = static_cast(that); This->lastMatch.mark(e); - This->lastInput->mark(e); + if (This->lastInput) + This->lastInput->mark(e); FunctionObject::markObjects(that, e); } -- cgit v1.2.3 From 2f16dd7b1415995109bc44b925cf860236977776 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 21 Dec 2016 07:09:03 +0100 Subject: Add some asserts to help debugging Change-Id: I49419e45ee2686e6e8646c49b839b4d77f2e05fd Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4runtime.cpp | 1 + src/qml/jsruntime/qv4string.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index d6c55926b1..023a739e33 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -499,6 +499,7 @@ Heap::String *RuntimeHelpers::convertToString(ExecutionEngine *engine, const Val { Scope scope(engine); ScopedValue prim(scope, RuntimeHelpers::toPrimitive(value, STRING_HINT)); + Q_ASSERT(!prim->isManaged() || prim->isString()); return RuntimeHelpers::convertToString(engine, prim); } case Value::Integer_Type: diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index 1efd8cb714..9494142fa5 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -102,6 +102,7 @@ void Heap::String::init(MemoryManager *mm, String *l, String *r) stringHash = UINT_MAX; largestSubLength = qMax(l->largestSubLength, r->largestSubLength); len = l->len + r->len; + Q_ASSERT(largestSubLength <= len); if (!l->largestSubLength && l->len > largestSubLength) largestSubLength = l->len; -- cgit v1.2.3 From 94e6106d357ca5a1349a2b10a69dd84db34065c8 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 3 Jan 2017 11:38:00 +0100 Subject: Simplify handling of non GC managed heap data Let the destroy() method in QV4::String clean up the unmanaged heap size instead of having a special hook in the code that sweeps the GC heap. Change-Id: I989ee99604f0cc67b896d3acc94e200dd5e56a60 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4string.cpp | 11 ++++++++++- src/qml/jsruntime/qv4string_p.h | 6 +----- src/qml/memory/qv4mm.cpp | 15 +++------------ src/qml/memory/qv4mm_p.h | 2 +- 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index 9494142fa5..cde2131aab 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -114,6 +114,15 @@ void Heap::String::init(MemoryManager *mm, String *l, String *r) simplifyString(); } +void Heap::String::destroy() { + if (!largestSubLength) { + mm->changeUnmanagedHeapSizeUsage(qptrdiff(-text->size) * (int)sizeof(QChar)); + if (!text->ref.deref()) + QStringData::deallocate(text); + } + Base::destroy(); +} + uint String::toUInt(bool *ok) const { *ok = true; @@ -152,7 +161,7 @@ void Heap::String::simplifyString() const text->ref.ref(); identifier = 0; largestSubLength = 0; - mm->growUnmanagedHeapSizeUsage(size_t(text->size) * sizeof(QChar)); + mm->changeUnmanagedHeapSizeUsage(qptrdiff(text->size) * (qptrdiff)sizeof(QChar)); } void Heap::String::append(const String *data, QChar *ch) diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index 4890a85724..5b0fd292d6 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -73,11 +73,7 @@ struct Q_QML_PRIVATE_EXPORT String : Base { #ifndef V4_BOOTSTRAP void init(MemoryManager *mm, const QString &text); void init(MemoryManager *mm, String *l, String *n); - void destroy() { - if (!largestSubLength && !text->ref.deref()) - QStringData::deallocate(text); - Base::destroy(); - } + void destroy(); void simplifyString() const; int length() const { Q_ASSERT((largestSubLength && diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 8732b02685..51eb82059a 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -194,10 +194,8 @@ struct MemoryManager::Data namespace { -bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, ExecutionEngine *engine, std::size_t *unmanagedHeapSize) +bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, ExecutionEngine *engine) { - Q_ASSERT(unmanagedHeapSize); - bool isEmpty = true; Heap::Base *tail = &header->freeItems; // qDebug("chunkStart @ %p, size=%x, pos=%x", header->itemStart, header->itemSize, header->itemSize>>4); @@ -222,13 +220,6 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec #ifdef V4_USE_VALGRIND VALGRIND_ENABLE_ERROR_REPORTING; #endif - if (std::size_t(header->itemSize) == MemoryManager::align(sizeof(Heap::String)) && m->vtable()->isString) { - std::size_t heapBytes = static_cast(m)->retainedTextSize(); - Q_ASSERT(*unmanagedHeapSize >= heapBytes); -// qDebug() << "-- it's a string holding on to" << heapBytes << "bytes"; - *unmanagedHeapSize -= heapBytes; - } - if (m->vtable()->destroy) { m->vtable()->destroy(m); m->_checkIsDestroyed(); @@ -502,7 +493,7 @@ void MemoryManager::sweep(bool lastSweep) for (size_t i = 0; i < m_d->heapChunks.size(); ++i) { Data::ChunkHeader *header = reinterpret_cast(m_d->heapChunks[i].base()); - chunkIsEmpty[i] = sweepChunk(header, &itemsInUse[header->itemSize >> 4], engine, &m_d->unmanagedHeapSize); + chunkIsEmpty[i] = sweepChunk(header, &itemsInUse[header->itemSize >> 4], engine); } std::vector::iterator chunkIter = m_d->heapChunks.begin(); @@ -642,7 +633,7 @@ size_t MemoryManager::getLargeItemsMem() const return total; } -void MemoryManager::growUnmanagedHeapSizeUsage(size_t delta) +void MemoryManager::changeUnmanagedHeapSizeUsage(qptrdiff delta) { m_d->unmanagedHeapSize += delta; } diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index 86a0ba2735..e6417cb2e0 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -297,7 +297,7 @@ public: size_t getAllocatedMem() const; size_t getLargeItemsMem() const; - void growUnmanagedHeapSizeUsage(size_t delta); // called when a JS object grows itself. Specifically: Heap::String::append + void changeUnmanagedHeapSizeUsage(qptrdiff delta); // called when a JS object grows itself. Specifically: Heap::String::append protected: /// expects size to be aligned -- cgit v1.2.3 From 63ce81bb052a5c462cf30f2e4293466fb9084f5a Mon Sep 17 00:00:00 2001 From: Julien Gueytat Date: Tue, 18 Oct 2016 10:21:55 +0200 Subject: No need to define c99 math functions in c++11 mode Change-Id: I5a04cb678ad4a222d2a716dd1499f5103bb66c8e Reviewed-by: Simon Hausmann --- src/3rdparty/masm/wtf/MathExtras.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty/masm/wtf/MathExtras.h b/src/3rdparty/masm/wtf/MathExtras.h index 75e3670367..3740d54beb 100644 --- a/src/3rdparty/masm/wtf/MathExtras.h +++ b/src/3rdparty/masm/wtf/MathExtras.h @@ -88,7 +88,7 @@ inline double wtf_ceil(double x) { return copysign(ceil(x), x); } #endif -#if OS(SOLARIS) +#if OS(SOLARIS) && __cplusplus < 201103L namespace std { -- cgit v1.2.3 From c4067b42f7ab359ed8d1285211a3eb2311ed5338 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Thu, 19 Jan 2017 16:10:09 +0100 Subject: Do not leak the item, and use a QScopedPointer to guarantee cleanup Change-Id: Ib4160f418686cef6d85dfd64657d25836f66778e Reviewed-by: Shawn Rutledge --- tests/auto/quick/qquickloader/tst_qquickloader.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp index 77af4796b6..3e7439f3e9 100644 --- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp +++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp @@ -469,7 +469,7 @@ void tst_QQuickLoader::networkComponent() // because in the synchronous case we're already done loading. QTRY_COMPARE(component.status(), QQmlComponent::Ready); - QQuickItem *item = qobject_cast(component.create()); + QScopedPointer item(qobject_cast(component.create())); QVERIFY(item); QQuickLoader *loader = qobject_cast(item->children().at(1)); @@ -481,7 +481,6 @@ void tst_QQuickLoader::networkComponent() QCOMPARE(loader->status(), QQuickLoader::Ready); QCOMPARE(static_cast(loader)->children().count(), 1); - delete loader; } void tst_QQuickLoader::failNetworkRequest() -- cgit v1.2.3 From f1c37497238be8960a5408fc3b7abc65c3774061 Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Wed, 18 Jan 2017 22:04:50 +0900 Subject: Fix build without features.localserver Change-Id: I25edd84fb67f417caa98e63f284547eac3a7793a Reviewed-by: Lars Knoll --- src/src.pro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/src.pro b/src/src.pro index f585ef15ca..21925c9330 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,7 +1,7 @@ TEMPLATE = subdirs CONFIG += ordered include($$OUT_PWD/quick/qtquick-config.pri) -QT_FOR_CONFIG += quick-private +QT_FOR_CONFIG += network quick-private SUBDIRS += \ qml @@ -20,6 +20,6 @@ SUBDIRS += \ imports \ qmldevtools -!contains(QT_CONFIG, no-qml-debug): SUBDIRS += qmldebug +qtConfig(localserver):!contains(QT_CONFIG, no-qml-debug): SUBDIRS += qmldebug qmldevtools.CONFIG = host_build -- cgit v1.2.3 From fb36e37928a6267a4f1881995b3aa53740a0a399 Mon Sep 17 00:00:00 2001 From: Aram So Date: Mon, 23 Jan 2017 11:12:42 +0900 Subject: Doc: Added a description of visible in MouseArea Task-number: QTBUG-56881 Change-Id: I5e1614c2854b166f87b20804e13d7686e11f3a3a Reviewed-by: Robin Burchell --- src/quick/items/qquickmousearea.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index 2f66bbebf2..bb23b1fd54 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -206,6 +206,9 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i the proxied item. When disabled, the mouse area becomes transparent to mouse events. + MouseArea is an invisible Item, but it has a visible property. + When set to false, the mouse area becomes transparent to mouse events. + The \l pressed read-only property indicates whether or not the user is holding down a mouse button over the mouse area. This property is often used in bindings between properties in a user interface. The containsMouse -- cgit v1.2.3 From 325051bc42cd081bfd3a698a16c44235164be2af Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Mon, 9 Jan 2017 16:08:37 +0100 Subject: Remove qWarning about QQuickImageProviderWithOptions If you're an user it's a bit annoying since it may show a lot and you don't know what to do with it If you're a developer it's a bit annoying since it's telling you to use a private class If we had a "debug for developers only mode" we could improve the message to be a bit more fine tuned and suggest that if they really want to be precise they can implement QQuickImageProviderWithOptions but as far as i know we don't have it, so i think it's better to remove the message altogether. Also mark the internal classes with the private export and add \internal to documentation of the internal class Change-Id: I5d7fc8d8b333c9a12321ed8135433603251815fc Reviewed-by: Robin Burchell --- src/quick/util/qquickimageprovider.cpp | 2 +- src/quick/util/qquickpixmapcache.cpp | 9 --------- src/quick/util/qquickpixmapcache_p.h | 4 ++-- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp index c4182d9f93..7788635e3e 100644 --- a/src/quick/util/qquickimageprovider.cpp +++ b/src/quick/util/qquickimageprovider.cpp @@ -514,9 +514,9 @@ public: /*! \class QQuickImageProviderOptions - \since 5.9 \brief The QQuickImageProviderOptions class provides options for QQuickImageProviderWithOptions image requests. \inmodule QtQuick + \internal \sa QQuickImageProviderWithOptions */ diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp index 7b369a2d0f..1c6b2afb54 100644 --- a/src/quick/util/qquickpixmapcache.cpp +++ b/src/quick/util/qquickpixmapcache.cpp @@ -695,15 +695,6 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u QQuickImageProviderWithOptions *providerV2 = provider->d->isProviderWithOptions ? static_cast(provider) : nullptr; - if (!provider->d->isProviderWithOptions && - (providerOptions.autoTransform() != QQuickImageProviderOptions::UsePluginDefaultTransform - || providerOptions.preserveAspectRatioCrop() - || providerOptions.preserveAspectRatioFit()) - ) - { - qWarning() << "Trying to pass extra request flags to provider but it is not a QQuickImageProviderWithOptions"; - } - switch (imageType) { case QQuickImageProvider::Invalid: { diff --git a/src/quick/util/qquickpixmapcache_p.h b/src/quick/util/qquickpixmapcache_p.h index eea6a7a454..f7cdfa7d07 100644 --- a/src/quick/util/qquickpixmapcache_p.h +++ b/src/quick/util/qquickpixmapcache_p.h @@ -91,7 +91,7 @@ public: }; // ### Qt 6: Make public moving to qquickimageprovider.h -class Q_QUICK_EXPORT QQuickImageProviderOptions +class Q_QUICK_PRIVATE_EXPORT QQuickImageProviderOptions { public: enum AutoTransform { @@ -188,7 +188,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickPixmap::Options) // This class will disappear with Qt6 and will just be the regular QQuickImageProvider // ### Qt 6: Remove this class and fold it with QQuickImageProvider -class Q_QUICK_EXPORT QQuickImageProviderWithOptions : public QQuickAsyncImageProvider +class Q_QUICK_PRIVATE_EXPORT QQuickImageProviderWithOptions : public QQuickAsyncImageProvider { public: QQuickImageProviderWithOptions(ImageType type, Flags flags = Flags()); -- cgit v1.2.3 From 432eb3344b0581ea1915840365b71376388a75b2 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Tue, 10 Jan 2017 10:50:43 +0100 Subject: Blacklist qmltest::mouserelease::test_mouseDrag() on RHEL 7.2 Task-number: QTBUG-58025 Change-Id: I0768ea834d5666f2831f24c3b2c71b7a4260d5d9 Reviewed-by: Simon Hausmann --- tests/auto/qmltest/BLACKLIST | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/qmltest/BLACKLIST b/tests/auto/qmltest/BLACKLIST index c38347b42a..fd796fcdb4 100644 --- a/tests/auto/qmltest/BLACKLIST +++ b/tests/auto/qmltest/BLACKLIST @@ -9,3 +9,5 @@ linux linux [ListView::test_listInteractiveCurrentIndexEnforce] linux +[mouserelease::test_mouseDrag] +rhel-7.2 -- cgit v1.2.3 From 94f6071b8a36501d9da516f2bf0f251147c8b934 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Thu, 29 Dec 2016 11:43:27 +0100 Subject: Fix qtdeclarative compilation On ubuntu 14.04 building qtdeclarative from the dev branch is impossible due to various errors in the openvg plugin. Change-Id: I1f2d7d61c36428e64cf3248e550ac5c4f0baa4b0 Reviewed-by: Paolo Angelelli --- src/plugins/scenegraph/openvg/openvg.pro | 1 + .../scenegraph/openvg/qopenvgoffscreensurface.cpp | 5 +- src/plugins/scenegraph/openvg/qsgopenvgcontext.cpp | 4 +- .../scenegraph/openvg/qsgopenvgpublicnodes.cpp | 73 ++++++++++++++++++++++ .../scenegraph/openvg/qsgopenvgpublicnodes.h | 32 +++++----- 5 files changed, 93 insertions(+), 22 deletions(-) diff --git a/src/plugins/scenegraph/openvg/openvg.pro b/src/plugins/scenegraph/openvg/openvg.pro index 8a58796a05..6d5b190b37 100644 --- a/src/plugins/scenegraph/openvg/openvg.pro +++ b/src/plugins/scenegraph/openvg/openvg.pro @@ -10,6 +10,7 @@ QMAKE_TARGET_PRODUCT = "Qt Quick OpenVG Renderer (Qt $$QT_VERSION)" QMAKE_TARGET_DESCRIPTION = "Quick OpenVG Renderer for Qt." QMAKE_USE += openvg +CONFIG += egl OTHER_FILES += $$PWD/openvg.json diff --git a/src/plugins/scenegraph/openvg/qopenvgoffscreensurface.cpp b/src/plugins/scenegraph/openvg/qopenvgoffscreensurface.cpp index 80af227fb4..1f2709e06c 100644 --- a/src/plugins/scenegraph/openvg/qopenvgoffscreensurface.cpp +++ b/src/plugins/scenegraph/openvg/qopenvgoffscreensurface.cpp @@ -37,10 +37,11 @@ ** ****************************************************************************/ +#include #include "qopenvgoffscreensurface.h" #include -#include + QT_BEGIN_NAMESPACE @@ -71,7 +72,7 @@ QOpenVGOffscreenSurface::QOpenVGOffscreenSurface(const QSize &size) m_renderTarget = eglCreatePbufferFromClientBuffer(m_display, EGL_OPENVG_IMAGE, - (EGLClientBuffer)m_image, + reinterpret_cast(uintptr_t(m_image)), pbufferConfig, 0); if (m_renderTarget == EGL_NO_SURFACE) diff --git a/src/plugins/scenegraph/openvg/qsgopenvgcontext.cpp b/src/plugins/scenegraph/openvg/qsgopenvgcontext.cpp index 22a80c62e8..41fce7c7fc 100644 --- a/src/plugins/scenegraph/openvg/qsgopenvgcontext.cpp +++ b/src/plugins/scenegraph/openvg/qsgopenvgcontext.cpp @@ -39,8 +39,6 @@ #include "qsgopenvgcontext_p.h" #include "qsgopenvgrenderer_p.h" -#include "qsgopenvginternalrectanglenode.h" -#include "qsgopenvginternalimagenode.h" #include "qsgopenvgpublicnodes.h" #include "qsgopenvgtexture.h" #include "qsgopenvglayer.h" @@ -52,6 +50,8 @@ #include "qopenvgcontext_p.h" #include +#include "qsgopenvginternalrectanglenode.h" +#include "qsgopenvginternalimagenode.h" // polish, animations, sync, render and swap in the render loop Q_LOGGING_CATEGORY(QSG_OPENVG_LOG_TIME_RENDERLOOP, "qt.scenegraph.time.renderloop") diff --git a/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp b/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp index 1afc5ea7ca..e45b79706b 100644 --- a/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp +++ b/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp @@ -39,6 +39,8 @@ #include "qsgopenvgpublicnodes.h" #include "qsgopenvghelpers.h" +#include +#include QT_BEGIN_NAMESPACE @@ -66,6 +68,11 @@ void QSGOpenVGRectangleNode::setRect(const QRectF &rect) markDirty(DirtyMaterial); } +QRectF QSGOpenVGRectangleNode::rect() const +{ + return m_rect; +} + void QSGOpenVGRectangleNode::setColor(const QColor &color) { m_color = color; @@ -73,6 +80,11 @@ void QSGOpenVGRectangleNode::setColor(const QColor &color) markDirty(DirtyMaterial); } +QColor QSGOpenVGRectangleNode::color() const +{ + return m_color; +} + void QSGOpenVGRectangleNode::setTransform(const QOpenVGMatrix &transform) { // if there transform matrix is not affine, regenerate the path @@ -177,12 +189,58 @@ QSGOpenVGImageNode::~QSGOpenVGImageNode() } } +void QSGOpenVGImageNode::setRect(const QRectF &rect) +{ + m_rect = rect; + markDirty(DirtyMaterial); +} + +QRectF QSGOpenVGImageNode::rect() const +{ + return m_rect; +} + +void QSGOpenVGImageNode::setSourceRect(const QRectF &r) +{ + m_sourceRect = r; +} + +QRectF QSGOpenVGImageNode::sourceRect() const +{ + return m_sourceRect; +} + void QSGOpenVGImageNode::setTexture(QSGTexture *texture) { m_texture = texture; markDirty(DirtyMaterial); } +QSGTexture *QSGOpenVGImageNode::texture() const +{ + return m_texture; +} + +void QSGOpenVGImageNode::setFiltering(QSGTexture::Filtering filtering) +{ + m_filtering = filtering; + markDirty(DirtyMaterial); +} + +QSGTexture::Filtering QSGOpenVGImageNode::filtering() const +{ + return m_filtering; +} + +void QSGOpenVGImageNode::setMipmapFiltering(QSGTexture::Filtering) +{ +} + +QSGTexture::Filtering QSGOpenVGImageNode::mipmapFiltering() const +{ + return QSGTexture::None; +} + void QSGOpenVGImageNode::setTextureCoordinatesTransform(QSGImageNode::TextureCoordinatesTransformMode transformNode) { if (m_transformMode == transformNode) @@ -191,6 +249,21 @@ void QSGOpenVGImageNode::setTextureCoordinatesTransform(QSGImageNode::TextureCoo markDirty(DirtyGeometry); } +QSGImageNode::TextureCoordinatesTransformMode QSGOpenVGImageNode::textureCoordinatesTransform() const +{ + return m_transformMode; +} + +void QSGOpenVGImageNode::setOwnsTexture(bool owns) +{ + m_owns = owns; +} + +bool QSGOpenVGImageNode::ownsTexture() const +{ + return m_owns; +} + void QSGOpenVGImageNode::render() { if (!m_texture) { diff --git a/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.h b/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.h index 34c8e50615..8e12c27824 100644 --- a/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.h +++ b/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.h @@ -44,10 +44,6 @@ #include #include -#include - -#include - #include "qsgopenvgrenderable.h" QT_BEGIN_NAMESPACE @@ -59,10 +55,10 @@ public: ~QSGOpenVGRectangleNode(); void setRect(const QRectF &rect) override; - QRectF rect() const override { return m_rect; } + QRectF rect() const override; void setColor(const QColor &color) override; - QColor color() const override { return m_color; } + QColor color() const override; void setTransform(const QOpenVGMatrix &transform) override; @@ -86,26 +82,26 @@ public: QSGOpenVGImageNode(); ~QSGOpenVGImageNode(); - void setRect(const QRectF &rect) override { m_rect = rect; markDirty(DirtyMaterial); } - QRectF rect() const override { return m_rect; } + void setRect(const QRectF &rect) override; + QRectF rect() const override; - void setSourceRect(const QRectF &r) override { m_sourceRect = r; } - QRectF sourceRect() const override { return m_sourceRect; } + void setSourceRect(const QRectF &r) override; + QRectF sourceRect() const override; void setTexture(QSGTexture *texture) override; - QSGTexture *texture() const override { return m_texture; } + QSGTexture *texture() const override; - void setFiltering(QSGTexture::Filtering filtering) override { m_filtering = filtering; markDirty(DirtyMaterial); } - QSGTexture::Filtering filtering() const override { return m_filtering; } + void setFiltering(QSGTexture::Filtering filtering) override; + QSGTexture::Filtering filtering() const override; - void setMipmapFiltering(QSGTexture::Filtering) override { } - QSGTexture::Filtering mipmapFiltering() const override { return QSGTexture::None; } + void setMipmapFiltering(QSGTexture::Filtering) override; + QSGTexture::Filtering mipmapFiltering() const override; void setTextureCoordinatesTransform(TextureCoordinatesTransformMode transformNode) override; - TextureCoordinatesTransformMode textureCoordinatesTransform() const override { return m_transformMode; } + TextureCoordinatesTransformMode textureCoordinatesTransform() const override; - void setOwnsTexture(bool owns) override { m_owns = owns; } - bool ownsTexture() const override { return m_owns; } + void setOwnsTexture(bool owns) override; + bool ownsTexture() const override; void render() override; -- cgit v1.2.3 From 941fb369ebfa7d44e5db0f589d81159fe156cf88 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Mon, 23 Jan 2017 14:56:50 +0100 Subject: Stabilize test Obviously, if the animation still hasn't stopped, we cannot expect it to fail on the next QTRY_COMPARE, since that might wait until it then passes, thus CI will log that as an XPASS. This failed during CI run for MSVC 2015: XPASS : tst_QPauseAnimationJob::multipleSequentialGroups() QCOMPARE(((group.state())), QAbstractAnimationJob::Stopped) returned TRUE unexpectedly. tst_qpauseanimationjob.cpp(396) : failure location Change-Id: I25151123b8fc2617f2a4d3690215e6a1ed2856ff Reviewed-by: Shawn Rutledge --- .../auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp b/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp index 1791407934..ff295c5409 100644 --- a/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp +++ b/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp @@ -392,8 +392,10 @@ void tst_QPauseAnimationJob::multipleSequentialGroups() #ifdef Q_OS_WIN if (group.state() != QAbstractAnimationJob::Stopped) QEXPECT_FAIL("", winTimerError, Abort); -#endif + QCOMPARE(group.state(), QAbstractAnimationJob::Stopped); +#else QTRY_COMPARE(group.state(), QAbstractAnimationJob::Stopped); +#endif #ifdef Q_OS_WIN if (subgroup1.state() != QAbstractAnimationJob::Stopped) -- cgit v1.2.3 From ca6b787a01ea289bd5c2a3e4ff3c7442a4ff58fc Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 14 Jun 2016 16:28:34 +0200 Subject: Allow canceling incubation Qt Quick Controls must avoid destroying any object that belongs to a tree of objects being incubated. The problem is that QQC have no control over the incubation process. This patch adds private API that allows QQC to cancel incubation of a specific item that QQC would like to destroy. Change-Id: Id9f9004736e2b53fe46cdb6bb3055b7457def94d Task-number: QTBUG-50992 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlincubator.cpp | 17 +++++++++++++++++ src/qml/qml/qqmlincubator_p.h | 5 +++++ src/qml/qml/qqmlobjectcreator.cpp | 15 +++++++++++++++ src/qml/qml/qqmlobjectcreator_p.h | 1 + src/qml/qml/qqmlvme.cpp | 12 ++++++++++++ src/qml/qml/qqmlvme_p.h | 1 + 6 files changed, 51 insertions(+) diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp index 963638ca34..54d0b240f5 100644 --- a/src/qml/qml/qqmlincubator.cpp +++ b/src/qml/qml/qqmlincubator.cpp @@ -380,6 +380,23 @@ finishIncubate: } } +void QQmlIncubatorPrivate::cancel(QObject *object, QQmlContext *context) +{ + if (!context) + context = qmlContext(object); + if (!context) + return; + + QQmlContextData *data = QQmlContextData::get(context); + QQmlIncubatorPrivate *p = (QQmlIncubatorPrivate *)data->activeVMEData; + if (!p) + return; + + p->vmeGuard.unguard(object); + if (!p->creator.isNull()) + p->creator->cancel(object); +} + /*! Incubate objects for \a msecs, or until there are no more objects to incubate. */ diff --git a/src/qml/qml/qqmlincubator_p.h b/src/qml/qml/qqmlincubator_p.h index ecf3b6d2ca..758e0a29f6 100644 --- a/src/qml/qml/qqmlincubator_p.h +++ b/src/qml/qml/qqmlincubator_p.h @@ -40,6 +40,8 @@ #ifndef QQMLINCUBATOR_P_H #define QQMLINCUBATOR_P_H +#include "qqmlincubator.h" + #include #include #include @@ -100,6 +102,9 @@ public: void forceCompletion(QQmlInstantiationInterrupt &i); void incubate(QQmlInstantiationInterrupt &i); + + // used by Qt Quick Controls 2 + Q_QML_PRIVATE_EXPORT static void cancel(QObject *object, QQmlContext *context = 0); }; QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 09936f6e7a..38a16b8cde 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -1270,6 +1270,21 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru return sharedState->rootContext; } +void QQmlObjectCreator::cancel(QObject *object) +{ + int last = sharedState->allCreatedObjects.count() - 1; + int i = last; + while (i >= 0) { + if (sharedState->allCreatedObjects.at(i) == object) { + if (i < last) + qSwap(sharedState->allCreatedObjects[i], sharedState->allCreatedObjects[last]); + sharedState->allCreatedObjects.pop(); + break; + } + --i; + } +} + void QQmlObjectCreator::clear() { if (phase == Done || phase == Finalizing || phase == Startup) diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h index caee7b9d1d..982324be3c 100644 --- a/src/qml/qml/qqmlobjectcreator_p.h +++ b/src/qml/qml/qqmlobjectcreator_p.h @@ -90,6 +90,7 @@ public: QObject *create(int subComponentIndex = -1, QObject *parent = 0, QQmlInstantiationInterrupt *interrupt = 0); bool populateDeferredProperties(QObject *instance); QQmlContextData *finalize(QQmlInstantiationInterrupt &interrupt); + void cancel(QObject *object); void clear(); QQmlComponentAttached **componentAttachment() const { return &sharedState->componentAttached; } diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index 72d4ab7e8f..c60f4edc80 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -120,6 +120,18 @@ void QQmlVMEGuard::guard(QQmlObjectCreator *creator) m_contexts[0] = creator->parentContextData(); } +void QQmlVMEGuard::unguard(QObject *object) +{ + for (int ii = 0; ii < m_objectCount; ++ii) { + if (m_objects[ii] == object) { + if (ii < m_objectCount - 1) + ::memmove((void *) m_objects[ii], (void *) m_objects[ii + 1], sizeof(QPointer *)); + delete m_objects[--m_objectCount]; + break; + } + } +} + void QQmlVMEGuard::clear() { delete [] m_objects; diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h index 99d63380ad..9585b5b6df 100644 --- a/src/qml/qml/qqmlvme_p.h +++ b/src/qml/qml/qqmlvme_p.h @@ -131,6 +131,7 @@ public: ~QQmlVMEGuard(); void guard(QQmlObjectCreator *); + void unguard(QObject *); void clear(); bool isOK() const; -- cgit v1.2.3 From b9fe2c2bfd99098ad06154d7fa8c104ac63a1257 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Tue, 24 Jan 2017 12:35:13 +0100 Subject: Teach QQmlDirParser to ignore the classname keyword This saves QQmlImport from some unnecessary bad lookups when finding types (due to classname being misinterpreted as belonging as a component). Change-Id: I36e622e357e55e98a5af46911709640c5d8fa291 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmldirparser.cpp | 9 +++++++++ tests/auto/qml/qqmldirparser/data/classname/qmldir | 5 +++++ tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp | 9 +++++++++ 3 files changed, 23 insertions(+) create mode 100644 tests/auto/qml/qqmldirparser/data/classname/qmldir diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qml/qqmldirparser.cpp index fde7cc4cef..4cca8a4d58 100644 --- a/src/qml/qml/qqmldirparser.cpp +++ b/src/qml/qml/qqmldirparser.cpp @@ -188,6 +188,15 @@ bool QQmlDirParser::parse(const QString &source) _plugins.append(entry); + } else if (sections[0] == QLatin1String("classname")) { + if (sectionCount < 2) { + reportError(lineNumber, 0, + QStringLiteral("classname directive requires an argument, but %1 were provided").arg(sectionCount - 1)); + + continue; + } + + // Ignore these. qmlimportscanner uses them. } else if (sections[0] == QLatin1String("internal")) { if (sectionCount != 3) { reportError(lineNumber, 0, diff --git a/tests/auto/qml/qqmldirparser/data/classname/qmldir b/tests/auto/qml/qqmldirparser/data/classname/qmldir new file mode 100644 index 0000000000..8167e813df --- /dev/null +++ b/tests/auto/qml/qqmldirparser/data/classname/qmldir @@ -0,0 +1,5 @@ +module QtQuick +plugin qtquick2plugin +classname QtQuick2Plugin +typeinfo plugins.qmltypes +designersupported diff --git a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp index 7d154d0ea6..3643ca65c6 100644 --- a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp +++ b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp @@ -325,6 +325,15 @@ void tst_qqmldirparser::parse_data() << QStringList() << (QStringList() << "bar||1|0|true") << false; + + QTest::newRow("classname") + << "classname/qmldir" + << QStringList() + << (QStringList() << "qtquick2plugin|") + << QStringList() + << QStringList() + << QStringList() + << true; } void tst_qqmldirparser::parse() -- cgit v1.2.3 From 6d4418243eeb87152ae159eb8e7d45be8a10b6fb Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Sun, 22 Jan 2017 12:41:09 +0100 Subject: QQmlTypeLoader: Deduplicate type resolution code Change-Id: I325a0c27f4a851d91876612c5eb2da08bd1fb75e Reviewed-by: Simon Hausmann --- src/qml/qml/qqmltypeloader.cpp | 50 +++++++----------------------------------- src/qml/qml/qqmltypeloader_p.h | 2 +- 2 files changed, 9 insertions(+), 43 deletions(-) diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index ac993a1037..5b1bba46dd 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2575,50 +2575,11 @@ void QQmlTypeData::resolveTypes() int majorVersion = -1; int minorVersion = -1; - QQmlImportNamespace *typeNamespace = 0; - QList errors; const QString name = stringAt(unresolvedRef.key()); - bool typeFound = m_importCache.resolveType(name, &ref.type, - &majorVersion, &minorVersion, &typeNamespace, &errors); - if (!typeNamespace && !typeFound && !m_implicitImportLoaded) { - // Lazy loading of implicit import - if (loadImplicitImport()) { - // Try again to find the type - errors.clear(); - typeFound = m_importCache.resolveType(name, &ref.type, - &majorVersion, &minorVersion, &typeNamespace, &errors); - } else { - return; //loadImplicitImport() hit an error, and called setError already - } - } - - if ((!typeFound || typeNamespace) && reportErrors) { - // Known to not be a type: - // - known to be a namespace (Namespace {}) - // - type with unknown namespace (UnknownNamespace.SomeType {}) - QQmlError error; - if (typeNamespace) { - error.setDescription(QQmlTypeLoader::tr("Namespace %1 cannot be used as a type").arg(name)); - } else { - if (errors.size()) { - error = errors.takeFirst(); - } else { - // this should not be possible! - // Description should come from error provided by addImport() function. - error.setDescription(QQmlTypeLoader::tr("Unreported error adding script import to import database")); - } - error.setUrl(m_importCache.baseUrl()); - error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(name).arg(error.description())); - } - error.setLine(unresolvedRef->location.line); - error.setColumn(unresolvedRef->location.column); - - errors.prepend(error); - setError(errors); + if (!resolveType(name, majorVersion, minorVersion, ref, unresolvedRef->location.line, unresolvedRef->location.column, reportErrors) && reportErrors) return; - } if (ref.type && ref.type->isComposite()) { ref.typeData = typeLoader()->getType(ref.type->sourceUrl()); @@ -2687,7 +2648,7 @@ QQmlCompileError QQmlTypeData::buildTypeResolutionCaches( return noError; } -bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref) +bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref, int lineNumber, int columnNumber, bool reportErrors) { QQmlImportNamespace *typeNamespace = 0; QList errors; @@ -2706,7 +2667,7 @@ bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int & } } - if (!typeFound || typeNamespace) { + if ((!typeFound || typeNamespace) && reportErrors) { // Known to not be a type: // - known to be a namespace (Namespace {}) // - type with unknown namespace (UnknownNamespace.SomeType {}) @@ -2725,6 +2686,11 @@ bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int & error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(typeName).arg(error.description())); } + if (lineNumber != -1) + error.setLine(lineNumber); + if (columnNumber != -1) + error.setColumn(columnNumber); + errors.prepend(error); setError(errors); return false; diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index b1d6451974..c60435a2d6 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -456,7 +456,7 @@ private: const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache); void createTypeAndPropertyCaches(const QQmlRefPointer &importCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache); - bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref); + bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref, int lineNumber = -1, int columnNumber = -1, bool reportErrors = true); void scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override; -- cgit v1.2.3 From ff1a728e957c36d566055caf922d160cbbbd7587 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Sat, 21 Jan 2017 21:13:23 +0100 Subject: tst_compilation: Add a test for compilation of a large number of types As I'll be touching QQmlImport, it would be good to ensure it doesn't regress. This may also be useful for future such changes (e.g. I want to try play around with how the implicit import is handled). Results for me on a recent dev snapshot, 2013 rmbp: ********* Start testing of tst_compilation ********* Config: Using QtTest library 5.9.0, Qt 5.9.0 (x86_64-little_endian-lp64 shared (dynamic) release build; by Clang 8.0.0 (clang-800.0.42.1) (Apple)) PASS : tst_compilation::initTestCase() PASS : tst_compilation::bigimport(10, qmldir) RESULT : tst_compilation::bigimport():"10, qmldir": 3.6 msecs per iteration (total: 59, iterations: 16) PASS : tst_compilation::bigimport(100, qmldir) RESULT : tst_compilation::bigimport():"100, qmldir": 54 msecs per iteration (total: 54, iterations: 1) PASS : tst_compilation::bigimport(1000, qmldir) RESULT : tst_compilation::bigimport():"1000, qmldir": 558 msecs per iteration (total: 558, iterations: 1) PASS : tst_compilation::bigimport(10, noqmldir) RESULT : tst_compilation::bigimport():"10, noqmldir": 5.0 msecs per iteration (total: 80, iterations: 16) PASS : tst_compilation::bigimport(100, noqmldir) RESULT : tst_compilation::bigimport():"100, noqmldir": 58 msecs per iteration (total: 58, iterations: 1) PASS : tst_compilation::bigimport(1000, noqmldir) RESULT : tst_compilation::bigimport():"1000, noqmldir": 558 msecs per iteration (total: 558, iterations: 1) PASS : tst_compilation::cleanupTestCase() Totals: 8 passed, 0 failed, 0 skipped, 0 blacklisted, 22400ms ********* Finished testing of tst_compilation ********* Change-Id: I7159e561fb13a3c48e966d5b963dc0ef1ca783e3 Reviewed-by: Simon Hausmann --- .../benchmarks/qml/compilation/tst_compilation.cpp | 71 ++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/tests/benchmarks/qml/compilation/tst_compilation.cpp b/tests/benchmarks/qml/compilation/tst_compilation.cpp index 61339c6f60..b28d69332c 100644 --- a/tests/benchmarks/qml/compilation/tst_compilation.cpp +++ b/tests/benchmarks/qml/compilation/tst_compilation.cpp @@ -51,6 +51,9 @@ private slots: void jsparser_data(); void jsparser(); + void bigimport_data(); + void bigimport(); + private: QQmlEngine engine; }; @@ -115,6 +118,74 @@ void tst_compilation::jsparser() } } +void tst_compilation::bigimport_data() +{ + QTest::addColumn("filesToCreate"); + QTest::addColumn("writeQmldir"); + + QTest::newRow("10, qmldir") + << 10 << true; + QTest::newRow("100, qmldir") + << 100 << true; + QTest::newRow("1000, qmldir") + << 1000 << true; + + QTest::newRow("10, noqmldir") + << 10 << false; + QTest::newRow("100, noqmldir") + << 100 << false; + QTest::newRow("1000, noqmldir") + << 1000 << false; +} + +void tst_compilation::bigimport() +{ + QFETCH(int, filesToCreate); + QFETCH(bool, writeQmldir); + QTemporaryDir d; + //d.setAutoRemove(false); // for debugging + + QString p; + { + for (int i = 0; i < filesToCreate; ++i) { + QFile f(d.path() + QDir::separator() + QString::fromLatin1("Type%1.qml").arg(i)); + QVERIFY(f.open(QIODevice::WriteOnly)); + f.write("import QtQuick 2.0\n"); + f.write("import \".\"\n"); + f.write("Item {}\n"); + } + + QFile qmldir(d.path() + QDir::separator() + "qmldir"); + if (writeQmldir) + QVERIFY(qmldir.open(QIODevice::WriteOnly)); + QFile main(d.path() + QDir::separator() + "main.qml"); + QVERIFY(main.open(QIODevice::WriteOnly)); + p = QFileInfo(main).absoluteFilePath(); + //qDebug() << p; // for debugging + + main.write("import QtQuick 2.0\n"); + main.write("import \".\"\n"); + main.write("\n"); + main.write("Item {\n"); + + for (int i = 0; i < filesToCreate; ++i) { + main.write(qPrintable(QString::fromLatin1("Type%1 {}\n").arg(i))); + if (writeQmldir) + qmldir.write(qPrintable(QString::fromLatin1("Type%1 1.0 Type%1.qml\n").arg(i))); + } + + main.write("}"); + } + + QBENCHMARK { + QQmlEngine e; + QQmlComponent c(&e, p); + QCOMPARE(c.status(), QQmlComponent::Ready); + QScopedPointer o(c.create()); + QVERIFY(o->children().count() == filesToCreate); + } +} + QTEST_MAIN(tst_compilation) #include "tst_compilation.moc" -- cgit v1.2.3 From f74b7b15979364d61a48e36315442c501bb9ea1a Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Mon, 23 Jan 2017 18:28:52 +0900 Subject: Fix build without qml-debug Change-Id: If4308195b05255a49a06184cab3db88ec9532f76 Reviewed-by: Lars Knoll --- src/qml/debugger/qqmlprofiler_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h index 3a507bef74..41fb2c5b7b 100644 --- a/src/qml/debugger/qqmlprofiler_p.h +++ b/src/qml/debugger/qqmlprofiler_p.h @@ -73,7 +73,7 @@ struct QQmlProfiler {}; struct QQmlBindingProfiler { - QQmlBindingProfiler(quintptr, QQmlBinding *, QV4::FunctionObject *) {} + QQmlBindingProfiler(quintptr, QV4::Function *) {} }; struct QQmlHandlingSignalProfiler -- cgit v1.2.3 From 9aed949bb99b9bf328322457a02ad1a9fb330f2d Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Mon, 23 Jan 2017 17:01:22 +0900 Subject: Fix build without features.commandlineparser Change-Id: I3a23e53fc647f5257593e0aece7198eea430cf14 Reviewed-by: Lars Knoll --- tools/qmllint/main.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/qmllint/main.cpp b/tools/qmllint/main.cpp index 211427cc64..45914353a8 100644 --- a/tools/qmllint/main.cpp +++ b/tools/qmllint/main.cpp @@ -29,7 +29,9 @@ #include #include #include +#if QT_CONFIG(commandlineparser) #include +#endif #include #include @@ -72,6 +74,7 @@ int main(int argv, char *argc[]) QCoreApplication app(argv, argc); QCoreApplication::setApplicationName("qmllint"); QCoreApplication::setApplicationVersion("1.0"); +#if QT_CONFIG(commandlineparser) QCommandLineParser parser; parser.setApplicationDescription(QLatin1String("QML syntax verifier")); parser.addHelpOption(); @@ -87,8 +90,15 @@ int main(int argv, char *argc[]) } bool silent = parser.isSet(silentOption); +#else + bool silent = false; +#endif bool success = true; +#if QT_CONFIG(commandlineparser) foreach (const QString &filename, parser.positionalArguments()) { +#else + foreach (const QString &filename, app.arguments()) { +#endif success &= lint_file(filename, silent); } -- cgit v1.2.3 From ac7a0ca517db963f8ecd82b9792f5fdcc85b78ae Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 22 Dec 2016 12:33:33 +0100 Subject: Add data structures that will get used for the new garbage collector Chunk is a 64k block of memory and the basic structure used in the new GC. HeapItem is a pointer to a slot of unallocated memory. When allocating memory, a number of HeapItems will get converted to a the correct class derived from Heap::Base. Change-Id: Id7c606df2d32501702330fbb6fa68ec66f62d6f9 Reviewed-by: Simon Hausmann --- src/qml/memory/memory.pri | 4 +- src/qml/memory/qv4mmdefs_p.h | 255 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 257 insertions(+), 2 deletions(-) create mode 100644 src/qml/memory/qv4mmdefs_p.h diff --git a/src/qml/memory/memory.pri b/src/qml/memory/memory.pri index 04b7566ccc..38fadbf23f 100644 --- a/src/qml/memory/memory.pri +++ b/src/qml/memory/memory.pri @@ -6,8 +6,8 @@ SOURCES += \ $$PWD/qv4mm.cpp \ HEADERS += \ - $$PWD/qv4mm_p.h - + $$PWD/qv4mm_p.h \ + $$PWD/qv4mmdefs_p.h } HEADERS += \ diff --git a/src/qml/memory/qv4mmdefs_p.h b/src/qml/memory/qv4mmdefs_p.h new file mode 100644 index 0000000000..4bfbfadde6 --- /dev/null +++ b/src/qml/memory/qv4mmdefs_p.h @@ -0,0 +1,255 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QV4MMDEFS_P_H +#define QV4MMDEFS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QV4 { + +/* + * Chunks are the basic structure containing GC managed objects. + * + * Chunks are 64k aligned in memory, so that retrieving the Chunk pointer from a Heap object + * is a simple masking operation. Each Chunk has 4 bitmaps for managing purposes, + * and 32byte wide slots for the objects following afterwards. + * + * The gray and black bitmaps are used for mark/sweep. + * The object bitmap has a bit set if this location represents the start of a Heap object. + * The extends bitmap denotes the extend of an object. It has a cleared bit at the start of the object + * and a set bit for all following slots used by the object. + * + * Free memory has both used and extends bits set to 0. + * + * This gives the following operations when allocating an object of size s: + * Find s/Alignment consecutive free slots in the chunk. Set the object bit for the first + * slot to 1. Set the extends bits for all following slots to 1. + * + * All used slots can be found by object|extents. + * + * When sweeping, simply copy the black bits over to the object bits. + * + */ +struct HeapItem; +struct Chunk { + enum { + ChunkSize = 64*1024, + ChunkShift = 16, + SlotSize = 32, + SlotSizeShift = 5, + NumSlots = ChunkSize/SlotSize, + BitmapSize = NumSlots/8, + HeaderSize = 4*BitmapSize, + DataSize = ChunkSize - HeaderSize, + AvailableSlots = DataSize/SlotSize, +#if QT_POINTER_SIZE == 8 + Bits = 64, + BitShift = 6, +#else + Bits = 32, + BitShift = 5, +#endif + EntriesInBitmap = BitmapSize/sizeof(quintptr) + }; + quintptr grayBitmap[BitmapSize/sizeof(quintptr)]; + quintptr blackBitmap[BitmapSize/sizeof(quintptr)]; + quintptr objectBitmap[BitmapSize/sizeof(quintptr)]; + quintptr extendsBitmap[BitmapSize/sizeof(quintptr)]; + char data[ChunkSize - HeaderSize]; + + HeapItem *realBase(); + HeapItem *first(); + + static void setBit(quintptr *bitmap, size_t index) { +// Q_ASSERT(index >= HeaderSize/SlotSize && index < ChunkSize/SlotSize); + bitmap += index >> BitShift; + quintptr bit = static_cast(1) << (index & (Bits - 1)); + *bitmap |= bit; + } + static void clearBit(quintptr *bitmap, size_t index) { +// Q_ASSERT(index >= HeaderSize/SlotSize && index < ChunkSize/SlotSize); + bitmap += index >> BitShift; + quintptr bit = static_cast(1) << (index & (Bits - 1)); + *bitmap &= ~bit; + } + static bool testBit(quintptr *bitmap, size_t index) { +// Q_ASSERT(index >= HeaderSize/SlotSize && index < ChunkSize/SlotSize); + bitmap += index >> BitShift; + quintptr bit = static_cast(1) << (index & (Bits - 1)); + return (*bitmap & bit); + } + static void setBits(quintptr *bitmap, size_t index, size_t nBits) { +// Q_ASSERT(index >= HeaderSize/SlotSize && index + nBits <= ChunkSize/SlotSize); + bitmap += index >> BitShift; + index &= (Bits - 1); + while (1) { + size_t bitsToSet = qMin(nBits, Bits - index); + quintptr mask = static_cast(-1) >> (Bits - bitsToSet) << index; + *bitmap |= mask; + nBits -= bitsToSet; + if (!nBits) + return; + index = 0; + ++bitmap; + } + } + static bool hasNonZeroBit(quintptr *bitmap) { + for (uint i = 0; i < EntriesInBitmap; ++i) + if (bitmap[i]) + return true; + return false; + } + static uint lowestNonZeroBit(quintptr *bitmap) { + for (uint i = 0; i < EntriesInBitmap; ++i) { + if (bitmap[i]) { + quintptr b = bitmap[i]; + return i*Bits + qCountTrailingZeroBits(b); + } + } + return 0; + } + + uint nFreeSlots() const { + return AvailableSlots - nUsedSlots(); + } + uint nUsedSlots() const { + uint usedSlots = 0; + for (uint i = 0; i < EntriesInBitmap; ++i) { + quintptr used = objectBitmap[i] | extendsBitmap[i]; + usedSlots += qPopulationCount(used); + } + return usedSlots; + } +}; + +struct HeapItem { + union { + struct { + HeapItem *next; + size_t availableSlots; + } freeData; + quint64 payload[Chunk::SlotSize/sizeof(quint64)]; + }; + operator Heap::Base *() { return reinterpret_cast(this); } + + template + T *as() { return static_cast(reinterpret_cast(this)); } + + Chunk *chunk() const { + return reinterpret_cast(reinterpret_cast(this) >> Chunk::ChunkShift << Chunk::ChunkShift); + } + + bool isGray() const { + Chunk *c = chunk(); + uint index = this - c->realBase(); + return Chunk::testBit(c->grayBitmap, index); + } + bool isBlack() const { + Chunk *c = chunk(); + uint index = this - c->realBase(); + return Chunk::testBit(c->blackBitmap, index); + } + bool isInUse() const { + Chunk *c = chunk(); + uint index = this - c->realBase(); + return Chunk::testBit(c->objectBitmap, index); + } + + void setAllocatedSlots(size_t nSlots) { +// Q_ASSERT(size && !(size % sizeof(HeapItem))); + Chunk *c = chunk(); + uint index = this - c->realBase(); +// Q_ASSERT(!Chunk::testBit(c->objectBitmap, index)); + Chunk::setBit(c->objectBitmap, index); + Chunk::setBits(c->extendsBitmap, index + 1, nSlots - 1); +// for (uint i = index + 1; i < nBits - 1; ++i) +// Q_ASSERT(Chunk::testBit(c->extendsBitmap, i)); +// Q_ASSERT(!Chunk::testBit(c->extendsBitmap, index)); + } + + // Doesn't report correctly for huge items + size_t size() const { + Chunk *c = chunk(); + uint index = this - c->realBase(); + Q_ASSERT(Chunk::testBit(c->objectBitmap, index)); + // ### optimize me + uint end = index + 1; + while (end < Chunk::NumSlots && Chunk::testBit(c->extendsBitmap, end)) + ++end; + return (end - index)*sizeof(HeapItem); + } +}; + +inline HeapItem *Chunk::realBase() +{ + return reinterpret_cast(this); +} + +inline HeapItem *Chunk::first() +{ + return reinterpret_cast(data); +} + +Q_STATIC_ASSERT(sizeof(Chunk) == Chunk::ChunkSize); +Q_STATIC_ASSERT((1 << Chunk::ChunkShift) == Chunk::ChunkSize); +Q_STATIC_ASSERT(1 << Chunk::SlotSizeShift == Chunk::SlotSize); +Q_STATIC_ASSERT(sizeof(HeapItem) == Chunk::SlotSize); +Q_STATIC_ASSERT(QT_POINTER_SIZE*8 == Chunk::Bits); +Q_STATIC_ASSERT((1 << Chunk::BitShift) == Chunk::Bits); + +} + +QT_END_NAMESPACE + +#endif -- cgit v1.2.3 From e97dd97a10fada91d9b50f129fa733e09971e6d7 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 22 Dec 2016 13:27:28 +0100 Subject: Align allocations to multiples of Chunk::SlotSize Change-Id: I13612d055b50331afa5eb9a9b61f4fd2d29b90bd Reviewed-by: Simon Hausmann --- src/qml/memory/qv4mm_p.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index e6417cb2e0..da8579f0dc 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -55,6 +55,7 @@ #include #include #include +#include #include //#define DETAILED_MM_STATS @@ -83,7 +84,7 @@ public: // TODO: this is only for 64bit (and x86 with SSE/AVX), so exend it for other architectures to be slightly more efficient (meaning, align on 8-byte boundaries). // Note: all occurrences of "16" in alloc/dealloc are also due to the alignment. static inline std::size_t align(std::size_t size) - { return (size + 15) & ~0xf; } + { return (size + Chunk::SlotSize - 1) & ~(Chunk::SlotSize - 1); } template inline typename ManagedType::Data *allocManaged(std::size_t size, std::size_t unmanagedSize = 0) -- cgit v1.2.3 From 550b71da1f48a73e3a9565d49ed5972886a584fc Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 22 Dec 2016 13:28:24 +0100 Subject: Always allocate in 64k chunks Cleans up the code a bit in preparation of the new GC. Has minimal effect on performance these days. Change-Id: Ifa6afea9acf8b6f086412e7eab7fa37c5387c624 Reviewed-by: Simon Hausmann --- src/qml/memory/qv4mm.cpp | 41 +---------------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 51eb82059a..28d664c35f 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -79,36 +79,6 @@ using namespace WTF; QT_BEGIN_NAMESPACE -static uint maxShiftValue() -{ - static uint result = 0; - if (!result) { - result = 6; - if (Q_UNLIKELY(qEnvironmentVariableIsSet(QV4_MM_MAXBLOCK_SHIFT))) { - bool ok; - const uint overrideValue = qgetenv(QV4_MM_MAXBLOCK_SHIFT).toUInt(&ok); - if (ok && overrideValue <= 11 && overrideValue > 0) - result = overrideValue; - } - } - return result; -} - -static std::size_t maxChunkSizeValue() -{ - static std::size_t result = 0; - if (!result) { - result = 32 * 1024; - if (Q_UNLIKELY(qEnvironmentVariableIsSet(QV4_MM_MAX_CHUNK_SIZE))) { - bool ok; - const std::size_t overrideValue = qgetenv(QV4_MM_MAX_CHUNK_SIZE).toUInt(&ok); - if (ok) - result = overrideValue; - } - } - return result; -} - using namespace QV4; struct MemoryManager::Data @@ -125,7 +95,6 @@ struct MemoryManager::Data ExecutionEngine *engine; - std::size_t maxChunkSize; std::vector heapChunks; std::size_t unmanagedHeapSize; // the amount of bytes of heap that is not managed by the memory manager, but which is held onto by managed items. std::size_t unmanagedHeapSizeGCLimit; @@ -150,7 +119,6 @@ struct MemoryManager::Data uint allocCount[MaxItemSize/16]; int totalItems; int totalAlloc; - uint maxShift; bool gcBlocked; bool aggressiveGC; @@ -165,14 +133,12 @@ struct MemoryManager::Data Data() : pageSize(WTF::pageSize()) , engine(0) - , maxChunkSize(maxChunkSizeValue()) , unmanagedHeapSize(0) , unmanagedHeapSizeGCLimit(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT) , largeItems(0) , totalLargeItemsAllocated(0) , totalItems(0) , totalAlloc(0) - , maxShift(maxShiftValue()) , gcBlocked(false) , aggressiveGC(!qEnvironmentVariableIsEmpty("QV4_MM_AGGRESSIVE_GC")) , gcStats(!qEnvironmentVariableIsEmpty(QV4_MM_STATS)) @@ -327,12 +293,7 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize // no free item available, allocate a new chunk { - // allocate larger chunks at a time to avoid excessive GC, but cap at maximum chunk size (2MB by default) - uint shift = ++m_d->nChunks[pos]; - if (shift > m_d->maxShift) - shift = m_d->maxShift; - std::size_t allocSize = m_d->maxChunkSize*(size_t(1) << shift); - allocSize = roundUpToMultipleOf(m_d->pageSize, allocSize); + std::size_t allocSize = QV4::Chunk::ChunkSize; Q_V4_PROFILE_ALLOC(engine, allocSize, Profiling::HeapPage); PageAllocation allocation = PageAllocation::allocate(allocSize, OSAllocator::JSGCHeapPages); m_d->heapChunks.push_back(allocation); -- cgit v1.2.3 From 90f055dbb44846b9ed37be8b9114573fcf2cd8ff Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 22 Dec 2016 15:20:05 +0100 Subject: Implement an allocator for Chunks Change-Id: I7c054cda95d016ce8bb0b341730378afc15a3522 Reviewed-by: Simon Hausmann --- src/qml/memory/qv4mm.cpp | 172 ++++++++++++++++++++++++++++++++++++++++++++++- src/qml/memory/qv4mm_p.h | 3 +- 2 files changed, 173 insertions(+), 2 deletions(-) diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 28d664c35f..92d8170ece 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -42,8 +42,12 @@ #include "qv4objectproto_p.h" #include "qv4mm_p.h" #include "qv4qobjectwrapper_p.h" +#include +#include #include +#include "PageReservation.h" #include "PageAllocation.h" +#include "PageAllocationAligned.h" #include "StdLibExtras.h" #include @@ -56,6 +60,14 @@ #include "qv4alloca_p.h" #include "qv4profiling_p.h" +#define MM_DEBUG 0 + +#if MM_DEBUG +#define DEBUG qDebug() << "MM:" +#else +#define DEBUG if (1) ; else qDebug() << "MM:" +#endif + #ifdef V4_USE_VALGRIND #include #include @@ -79,7 +91,160 @@ using namespace WTF; QT_BEGIN_NAMESPACE -using namespace QV4; +namespace QV4 { + +enum { + MinSlotsGCLimit = QV4::Chunk::AvailableSlots*16, + GCOverallocation = 200 /* Max overallocation by the GC in % */ +}; + +struct MemorySegment { + enum { + NumChunks = 8*sizeof(quint64), + SegmentSize = NumChunks*Chunk::ChunkSize, + }; + + MemorySegment(size_t size) + { + size += Chunk::ChunkSize; // make sure we can get enough 64k aligment memory + if (size < SegmentSize) + size = SegmentSize; + + pageReservation = PageReservation::reserve(size, OSAllocator::JSGCHeapPages); + base = reinterpret_cast((reinterpret_cast(pageReservation.base()) + Chunk::ChunkSize - 1) & ~(Chunk::ChunkSize - 1)); + nChunks = NumChunks; + if (base != pageReservation.base()) + --nChunks; + } + MemorySegment(MemorySegment &&other) { + qSwap(pageReservation, other.pageReservation); + qSwap(base, other.base); + qSwap(nChunks, other.nChunks); + qSwap(allocatedMap, other.allocatedMap); + } + + ~MemorySegment() { + if (base) + pageReservation.deallocate(); + } + + void setBit(size_t index) { + Q_ASSERT(index < nChunks); + quint64 bit = static_cast(1) << index; +// qDebug() << " setBit" << hex << index << (index & (Bits - 1)) << bit; + allocatedMap |= bit; + } + void clearBit(size_t index) { + Q_ASSERT(index < nChunks); + quint64 bit = static_cast(1) << index; +// qDebug() << " setBit" << hex << index << (index & (Bits - 1)) << bit; + allocatedMap &= ~bit; + } + bool testBit(size_t index) const { + Q_ASSERT(index < nChunks); + quint64 bit = static_cast(1) << index; + return (allocatedMap & bit); + } + + Chunk *allocate(size_t size); + void free(Chunk *chunk, size_t size) { + DEBUG << "freeing chunk" << chunk; + size_t index = static_cast(chunk - base); + size_t end = index + (size - 1)/Chunk::ChunkSize + 1; + while (index < end) { + Q_ASSERT(testBit(index)); + clearBit(index); + ++index; + } + + size_t pageSize = WTF::pageSize(); + size = (size + pageSize - 1) & ~(pageSize - 1); + pageReservation.decommit(chunk, size); + } + + bool contains(Chunk *c) const { + return c >= base && c < base + nChunks; + } + + PageReservation pageReservation; + Chunk *base = 0; + quint64 allocatedMap = 0; + uint nChunks = 0; +}; + +Chunk *MemorySegment::allocate(size_t size) +{ + size_t requiredChunks = (size + sizeof(Chunk) - 1)/sizeof(Chunk); + uint sequence = 0; + Chunk *candidate = 0; + for (uint i = 0; i < nChunks; ++i) { + if (!testBit(i)) { + if (!candidate) + candidate = base + i; + ++sequence; + } else { + candidate = 0; + sequence = 0; + } + if (sequence == requiredChunks) { + pageReservation.commit(candidate, size); + for (uint i = 0; i < requiredChunks; ++i) + setBit(candidate - base + i); + DEBUG << "allocated chunk " << candidate << hex << size; + return candidate; + } + } + return 0; +} + +struct ChunkAllocator { + ChunkAllocator() {} + + size_t requiredChunkSize(size_t size) { + size += Chunk::HeaderSize; // space required for the Chunk header + size_t pageSize = WTF::pageSize(); + size = (size + pageSize - 1) & ~(pageSize - 1); // align to page sizes + if (size < Chunk::ChunkSize) + size = Chunk::ChunkSize; + return size; + } + + Chunk *allocate(size_t size = 0); + void free(Chunk *chunk, size_t size = 0); + + std::vector memorySegments; +}; + +Chunk *ChunkAllocator::allocate(size_t size) +{ + size = requiredChunkSize(size); + for (auto &m : memorySegments) { + if (~m.allocatedMap) { + Chunk *c = m.allocate(size); + if (c) + return c; + } + } + + // allocate a new segment + memorySegments.push_back(MemorySegment(size)); + Chunk *c = memorySegments.back().allocate(size); + Q_ASSERT(c); + return c; +} + +void ChunkAllocator::free(Chunk *chunk, size_t size) +{ + size = requiredChunkSize(size); + for (auto &m : memorySegments) { + if (m.contains(chunk)) { + m.free(chunk, size); + return; + } + } + Q_ASSERT(false); +} + struct MemoryManager::Data { @@ -218,6 +383,7 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec MemoryManager::MemoryManager(ExecutionEngine *engine) : engine(engine) + , chunkAllocator(new ChunkAllocator) , m_d(new Data) , m_persistentValues(new PersistentValueStorage(engine)) , m_weakValues(new PersistentValueStorage(engine)) @@ -609,6 +775,7 @@ MemoryManager::~MemoryManager() #ifdef V4_USE_VALGRIND VALGRIND_DESTROY_MEMPOOL(this); #endif + delete chunkAllocator; } @@ -651,4 +818,7 @@ void MemoryManager::collectFromJSStack() const ++v; } } + +} // namespace QV4 + QT_END_NAMESPACE diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index da8579f0dc..f15b0fb62c 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -68,7 +68,7 @@ QT_BEGIN_NAMESPACE namespace QV4 { -struct GCDeletable; +struct ChunkAllocator; class Q_QML_EXPORT MemoryManager { @@ -316,6 +316,7 @@ private: public: QV4::ExecutionEngine *engine; + ChunkAllocator *chunkAllocator; QScopedPointer m_d; PersistentValueStorage *m_persistentValues; PersistentValueStorage *m_weakValues; -- cgit v1.2.3 From a325b21e1bd51263551829089e9f31e2156bc641 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 22 Dec 2016 21:24:27 +0100 Subject: Allocate simple call contexts from a special allocator We used to allocate those on the C stack, but this doesn't work anymore with the new GC, as the mark bit is not stored inside the object anymore. Instead use a special allocator for these contexts that operates like a stack. Change-Id: I381ac3914ca866945312a1e79883aefe72662d2c Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4context.cpp | 38 +++++++++++++++++------- src/qml/jsruntime/qv4context_p.h | 14 ++------- src/qml/jsruntime/qv4functionobject.cpp | 22 +++++++------- src/qml/memory/qv4mm.cpp | 45 ++++++++++++++++++++++++++++ src/qml/memory/qv4mm_p.h | 52 +++++++++++++++++++++++++++++++++ 5 files changed, 139 insertions(+), 32 deletions(-) diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 544d39339b..0954d621a6 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -95,6 +95,21 @@ Heap::CallContext *ExecutionContext::newCallContext(Function *function, CallData return c; } +Heap::CallContext *Heap::CallContext::createSimpleContext(ExecutionEngine *v4) +{ + Heap::CallContext *ctxt = v4->memoryManager->allocSimpleCallContext(); + memset(ctxt, 0, sizeof(Heap::CallContext)); + ctxt->mm_data = 0; + ctxt->setVtable(QV4::CallContext::staticVTable()); + ctxt->init(v4); + return ctxt; +} + +void Heap::CallContext::freeSimpleCallContext() +{ + engine->memoryManager->freeSimpleCallContext(); +} + Heap::WithContext *ExecutionContext::newWithContext(Heap::Object *with) { return d()->engine->memoryManager->alloc(d(), with); @@ -325,26 +340,27 @@ void QV4::ExecutionContext::simpleCall(Scope &scope, CallData *callData, Functio ExecutionContextSaver ctxSaver(scope); - CallContext::Data ctx = CallContext::Data::createOnStack(scope.engine); + CallContext::Data *ctx = CallContext::Data::createSimpleContext(scope.engine); - ctx.strictMode = function->isStrict(); - ctx.callData = callData; - ctx.v4Function = function; - ctx.compilationUnit = function->compilationUnit; - ctx.lookups = function->compilationUnit->runtimeLookups; - ctx.constantTable = function->compilationUnit->constants; - ctx.outer = this->d(); - ctx.locals = scope.alloc(function->compiledFunction->nLocals); + ctx->strictMode = function->isStrict(); + ctx->callData = callData; + ctx->v4Function = function; + ctx->compilationUnit = function->compilationUnit; + ctx->lookups = function->compilationUnit->runtimeLookups; + ctx->constantTable = function->compilationUnit->constants; + ctx->outer = this->d(); + ctx->locals = scope.alloc(function->compiledFunction->nLocals); for (int i = callData->argc; i < (int)function->nFormals; ++i) callData->args[i] = Encode::undefined(); - scope.engine->pushContext(&ctx); - Q_ASSERT(scope.engine->current == &ctx); + scope.engine->pushContext(ctx); + Q_ASSERT(scope.engine->current == ctx); scope.result = Q_V4_PROFILE(scope.engine, function); if (function->hasQmlDependencies) QQmlPropertyCapture::registerQmlDependencies(function->compiledFunction, scope); + ctx->freeSimpleCallContext(); } void ExecutionContext::setProperty(String *name, const Value &value) diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index c985fdb24d..996de174b4 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -135,7 +135,8 @@ struct ExecutionContext : Base { V4_ASSERT_IS_TRIVIAL(ExecutionContext) struct CallContext : ExecutionContext { - static CallContext createOnStack(ExecutionEngine *v4); + static CallContext *createSimpleContext(ExecutionEngine *v4); + void freeSimpleCallContext(); void init(ExecutionEngine *engine, ContextType t = Type_SimpleCallContext) { @@ -247,6 +248,7 @@ struct Q_QML_EXPORT CallContext : public ExecutionContext inline ReturnedValue argument(int i) const; bool needsOwnArguments() const; + }; inline ReturnedValue CallContext::argument(int i) const { @@ -289,16 +291,6 @@ inline const WithContext *ExecutionContext::asWithContext() const return d()->type == Heap::ExecutionContext::Type_WithContext ? static_cast(this) : 0; } -inline Heap::CallContext Heap::CallContext::createOnStack(ExecutionEngine *v4) -{ - Heap::CallContext ctxt; - memset(&ctxt, 0, sizeof(Heap::CallContext)); - ctxt.mm_data = 0; - ctxt.setVtable(QV4::CallContext::staticVTable()); - ctxt.init(v4); - return ctxt; -} - } // namespace QV4 QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 64f7b98618..1ac0e28a1b 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -484,13 +484,14 @@ void BuiltinFunction::call(const Managed *that, Scope &scope, CallData *callData ExecutionContextSaver ctxSaver(scope); - CallContext::Data ctx = CallContext::Data::createOnStack(v4); - ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context? - ctx.callData = callData; - v4->pushContext(&ctx); - Q_ASSERT(v4->current == &ctx); + CallContext::Data *ctx = CallContext::Data::createSimpleContext(v4); + ctx->strictMode = f->scope()->strictMode; // ### needed? scope or parent context? + ctx->callData = callData; + v4->pushContext(ctx); + Q_ASSERT(v4->current == ctx); scope.result = f->d()->code(static_cast(v4->currentContext)); + ctx->freeSimpleCallContext(); } void IndexedBuiltinFunction::call(const Managed *that, Scope &scope, CallData *callData) @@ -505,13 +506,14 @@ void IndexedBuiltinFunction::call(const Managed *that, Scope &scope, CallData *c ExecutionContextSaver ctxSaver(scope); - CallContext::Data ctx = CallContext::Data::createOnStack(v4); - ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context? - ctx.callData = callData; - v4->pushContext(&ctx); - Q_ASSERT(v4->current == &ctx); + CallContext::Data *ctx = CallContext::Data::createSimpleContext(v4); + ctx->strictMode = f->scope()->strictMode; // ### needed? scope or parent context? + ctx->callData = callData; + v4->pushContext(ctx); + Q_ASSERT(v4->current == ctx); scope.result = f->d()->code(static_cast(v4->currentContext), f->d()->index); + ctx->freeSimpleCallContext(); } DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction); diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 92d8170ece..96875c70f6 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -246,6 +246,49 @@ void ChunkAllocator::free(Chunk *chunk, size_t size) } +template +StackAllocator::StackAllocator(ChunkAllocator *chunkAlloc) + : chunkAllocator(chunkAlloc) +{ + chunks.push_back(chunkAllocator->allocate()); + firstInChunk = chunks.back()->first(); + nextFree = firstInChunk; + lastInChunk = firstInChunk + (Chunk::AvailableSlots - 1)/requiredSlots*requiredSlots; +} + +template +void StackAllocator::freeAll() +{ + for (auto c : chunks) + chunkAllocator->free(c); +} + +template +void StackAllocator::nextChunk() { + Q_ASSERT(nextFree == lastInChunk); + ++currentChunk; + if (currentChunk >= chunks.size()) { + Chunk *newChunk = chunkAllocator->allocate(); + chunks.push_back(newChunk); + } + firstInChunk = chunks.at(currentChunk)->first(); + nextFree = firstInChunk; + lastInChunk = firstInChunk + (Chunk::AvailableSlots - 1)/requiredSlots*requiredSlots; +} + +template +void QV4::StackAllocator::prevChunk() { + Q_ASSERT(nextFree == firstInChunk); + Q_ASSERT(chunks.at(currentChunk) == nextFree->chunk()); + Q_ASSERT(currentChunk > 0); + --currentChunk; + firstInChunk = chunks.at(currentChunk)->first(); + lastInChunk = firstInChunk + (Chunk::AvailableSlots - 1)/requiredSlots*requiredSlots; + nextFree = lastInChunk; +} + +template struct StackAllocator; + struct MemoryManager::Data { const size_t pageSize; @@ -384,6 +427,7 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec MemoryManager::MemoryManager(ExecutionEngine *engine) : engine(engine) , chunkAllocator(new ChunkAllocator) + , stackAllocator(chunkAllocator) , m_d(new Data) , m_persistentValues(new PersistentValueStorage(engine)) , m_weakValues(new PersistentValueStorage(engine)) @@ -770,6 +814,7 @@ MemoryManager::~MemoryManager() delete m_persistentValues; sweep(/*lastSweep*/true); + stackAllocator.freeAll(); delete m_weakValues; #ifdef V4_USE_VALGRIND diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index f15b0fb62c..52d95aca0c 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -64,12 +64,58 @@ #define QV4_MM_MAX_CHUNK_SIZE "QV4_MM_MAX_CHUNK_SIZE" #define QV4_MM_STATS "QV4_MM_STATS" +#define MM_DEBUG 0 + QT_BEGIN_NAMESPACE namespace QV4 { struct ChunkAllocator; +template +struct StackAllocator { + Q_STATIC_ASSERT(sizeof(T) < Chunk::DataSize); + static const uint requiredSlots = (sizeof(T) + sizeof(HeapItem) - 1)/sizeof(HeapItem); + + StackAllocator(ChunkAllocator *chunkAlloc); + + T *allocate() { + T *m = nextFree->as(); + if (Q_UNLIKELY(nextFree == lastInChunk)) { + nextChunk(); + } else { + nextFree += requiredSlots; + } +#if MM_DEBUG + Chunk *c = m->chunk(); + Chunk::setBit(c->objectBitmap, m - c->realBase()); +#endif + return m; + } + void free() { +#if MM_DEBUG + Chunk::clearBit(item->chunk()->objectBitmap, item - item->chunk()->realBase()); +#endif + if (Q_UNLIKELY(nextFree == firstInChunk)) { + prevChunk(); + } else { + nextFree -= requiredSlots; + } + } + + void nextChunk(); + void prevChunk(); + + void freeAll(); + + ChunkAllocator *chunkAllocator; + HeapItem *nextFree = 0; + HeapItem *firstInChunk = 0; + HeapItem *lastInChunk = 0; + std::vector chunks; + uint currentChunk = 0; +}; + class Q_QML_EXPORT MemoryManager { Q_DISABLE_COPY(MemoryManager); @@ -86,6 +132,11 @@ public: static inline std::size_t align(std::size_t size) { return (size + Chunk::SlotSize - 1) & ~(Chunk::SlotSize - 1); } + QV4::Heap::CallContext *allocSimpleCallContext() + { return stackAllocator.allocate(); } + void freeSimpleCallContext() + { stackAllocator.free(); } + template inline typename ManagedType::Data *allocManaged(std::size_t size, std::size_t unmanagedSize = 0) { @@ -317,6 +368,7 @@ private: public: QV4::ExecutionEngine *engine; ChunkAllocator *chunkAllocator; + StackAllocator stackAllocator; QScopedPointer m_d; PersistentValueStorage *m_persistentValues; PersistentValueStorage *m_weakValues; -- cgit v1.2.3 From 8cdd25357d29b958686089efcaaa5460a9855beb Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 20 Jan 2017 11:36:16 +0100 Subject: New allocator for huge items Use a new Chunk based allocator for very large items. Change-Id: Ie61a72efb6340cd9ef54e4fdd957d7ca36c8729f Reviewed-by: Simon Hausmann --- src/qml/memory/qv4mm.cpp | 100 ++++++++++++++++++++++------------------------- src/qml/memory/qv4mm_p.h | 27 +++++++++++++ 2 files changed, 73 insertions(+), 54 deletions(-) diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 96875c70f6..3b61273757 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -190,7 +190,6 @@ Chunk *MemorySegment::allocate(size_t size) pageReservation.commit(candidate, size); for (uint i = 0; i < requiredChunks; ++i) setBit(candidate - base + i); - DEBUG << "allocated chunk " << candidate << hex << size; return candidate; } } @@ -289,6 +288,45 @@ void QV4::StackAllocator::prevChunk() { template struct StackAllocator; +HeapItem *HugeItemAllocator::allocate(size_t size) { + Chunk *c = chunkAllocator->allocate(size); + chunks.push_back(HugeChunk{c, size}); + Chunk::setBit(c->objectBitmap, c->first() - c->realBase()); + return c->first(); +} + +static void freeHugeChunk(ChunkAllocator *chunkAllocator, const HugeItemAllocator::HugeChunk &c) +{ + HeapItem *itemToFree = c.chunk->first(); + Heap::Base *b = *itemToFree; + if (b->vtable()->destroy) { + b->vtable()->destroy(b); + b->_checkIsDestroyed(); + } + chunkAllocator->free(c.chunk, c.size); +} + +void HugeItemAllocator::sweep() { + auto isBlack = [this] (const HugeChunk &c) { + bool b = c.chunk->first()->isBlack(); + Chunk::clearBit(c.chunk->blackBitmap, c.chunk->first() - c.chunk->realBase()); + if (!b) + freeHugeChunk(chunkAllocator, c); + return !b; + }; + + auto newEnd = std::remove_if(chunks.begin(), chunks.end(), isBlack); + chunks.erase(newEnd, chunks.end()); +} + +void HugeItemAllocator::freeAll() +{ + for (auto &c : chunks) { + freeHugeChunk(chunkAllocator, c); + } +} + + struct MemoryManager::Data { const size_t pageSize; @@ -307,19 +345,6 @@ struct MemoryManager::Data std::size_t unmanagedHeapSize; // the amount of bytes of heap that is not managed by the memory manager, but which is held onto by managed items. std::size_t unmanagedHeapSizeGCLimit; - struct LargeItem { - LargeItem *next; - size_t size; - void *data; - - Heap::Base *heapObject() { - return reinterpret_cast(&data); - } - }; - - LargeItem *largeItems; - std::size_t totalLargeItemsAllocated; - enum { MaxItemSize = 512 }; ChunkHeader *nonFullChunks[MaxItemSize/16]; uint nChunks[MaxItemSize/16]; @@ -343,8 +368,6 @@ struct MemoryManager::Data , engine(0) , unmanagedHeapSize(0) , unmanagedHeapSizeGCLimit(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT) - , largeItems(0) - , totalLargeItemsAllocated(0) , totalItems(0) , totalAlloc(0) , gcBlocked(false) @@ -428,6 +451,7 @@ MemoryManager::MemoryManager(ExecutionEngine *engine) : engine(engine) , chunkAllocator(new ChunkAllocator) , stackAllocator(chunkAllocator) + , hugeItemAllocator(chunkAllocator) , m_d(new Data) , m_persistentValues(new PersistentValueStorage(engine)) , m_weakValues(new PersistentValueStorage(engine)) @@ -468,20 +492,8 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize // doesn't fit into a small bucket if (size >= MemoryManager::Data::MaxItemSize) { - if (!didGCRun && m_d->totalLargeItemsAllocated > 8 * 1024 * 1024) - runGC(); - - // we use malloc for this - const size_t totalSize = size + sizeof(MemoryManager::Data::LargeItem); - Q_V4_PROFILE_ALLOC(engine, totalSize, Profiling::LargeItem); - MemoryManager::Data::LargeItem *item = - static_cast(malloc(totalSize)); - memset(item, 0, totalSize); - item->next = m_d->largeItems; - item->size = size; - m_d->largeItems = item; - m_d->totalLargeItemsAllocated += size; - return item->heapObject(); + HeapItem *item = hugeItemAllocator.allocate(size); + return *item; } Heap::Base *m = 0; @@ -697,25 +709,7 @@ void MemoryManager::sweep(bool lastSweep) ++chunkIter; } - Data::LargeItem *i = m_d->largeItems; - Data::LargeItem **last = &m_d->largeItems; - while (i) { - Heap::Base *m = i->heapObject(); - Q_ASSERT(m->inUse()); - if (m->isMarked()) { - m->clearMarkBit(); - last = &i->next; - i = i->next; - continue; - } - if (m->vtable()->destroy) - m->vtable()->destroy(m); - - *last = i->next; - Q_V4_PROFILE_DEALLOC(engine, i->size + sizeof(Data::LargeItem), Profiling::LargeItem); - free(i); - i = *last; - } + hugeItemAllocator.sweep(); // some execution contexts are allocated on the stack, make sure we clear their markBit as well if (!lastSweep) { @@ -770,7 +764,6 @@ void MemoryManager::runGC() memset(m_d->allocCount, 0, sizeof(m_d->allocCount)); m_d->totalAlloc = 0; - m_d->totalLargeItemsAllocated = 0; } size_t MemoryManager::getUsedMem() const @@ -798,10 +791,7 @@ size_t MemoryManager::getAllocatedMem() const size_t MemoryManager::getLargeItemsMem() const { - size_t total = 0; - for (const Data::LargeItem *i = m_d->largeItems; i != 0; i = i->next) - total += i->size; - return total; + return hugeItemAllocator.usedMem(); } void MemoryManager::changeUnmanagedHeapSizeUsage(qptrdiff delta) @@ -814,6 +804,8 @@ MemoryManager::~MemoryManager() delete m_persistentValues; sweep(/*lastSweep*/true); + blockAllocator.freeAll(); + hugeItemAllocator.freeAll(); stackAllocator.freeAll(); delete m_weakValues; diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index 52d95aca0c..84769f33ba 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -116,6 +116,32 @@ struct StackAllocator { uint currentChunk = 0; }; +struct HugeItemAllocator { + HugeItemAllocator(ChunkAllocator *chunkAllocator) + : chunkAllocator(chunkAllocator) + {} + + HeapItem *allocate(size_t size); + void sweep(); + void freeAll(); + + size_t usedMem() const { + size_t used = 0; + for (const auto &c : chunks) + used += c.size; + return used; + } + + ChunkAllocator *chunkAllocator; + struct HugeChunk { + Chunk *chunk; + size_t size; + }; + + std::vector chunks; +}; + + class Q_QML_EXPORT MemoryManager { Q_DISABLE_COPY(MemoryManager); @@ -369,6 +395,7 @@ public: QV4::ExecutionEngine *engine; ChunkAllocator *chunkAllocator; StackAllocator stackAllocator; + HugeItemAllocator hugeItemAllocator; QScopedPointer m_d; PersistentValueStorage *m_persistentValues; PersistentValueStorage *m_weakValues; -- cgit v1.2.3 From a31a5a43b364ab70f10a7619234492dedd8c8dfe Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 3 Jan 2017 11:49:15 +0100 Subject: New garbage collector This is a block based allocator. We allocate HeapItems from 64k Chunks (except for huge items that get their own chunk). The allocator is block based, and aims to defragment when sweep'ing the blocks. The mark bit is now stored in the Chunk header, not inline in the object anymore. Change-Id: I2845f8b73dd496911ba50b868d54d144501d41e4 Reviewed-by: Simon Hausmann --- src/qml/memory/qv4heap_p.h | 19 +- src/qml/memory/qv4mm.cpp | 568 ++++++++++++++++++++++++------------------- src/qml/memory/qv4mm_p.h | 72 +++++- src/qml/memory/qv4mmdefs_p.h | 9 +- 4 files changed, 407 insertions(+), 261 deletions(-) diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h index 5a3797f397..f5172ec83c 100644 --- a/src/qml/memory/qv4heap_p.h +++ b/src/qml/memory/qv4heap_p.h @@ -52,6 +52,7 @@ #include #include +#include #include // To check if Heap::Base::init is called (meaning, all subclasses did their init and called their @@ -109,17 +110,23 @@ struct Q_QML_EXPORT Base { return reinterpret_cast(mm_data & PointerMask); } inline bool isMarked() const { - return mm_data & MarkBit; + const HeapItem *h = reinterpret_cast(this); + Chunk *c = h->chunk(); + Q_ASSERT(!Chunk::testBit(c->extendsBitmap, h - c->realBase())); + return Chunk::testBit(c->blackBitmap, h - c->realBase()); } inline void setMarkBit() { - mm_data |= MarkBit; - } - inline void clearMarkBit() { - mm_data &= ~MarkBit; + const HeapItem *h = reinterpret_cast(this); + Chunk *c = h->chunk(); + Q_ASSERT(!Chunk::testBit(c->extendsBitmap, h - c->realBase())); + return Chunk::setBit(c->blackBitmap, h - c->realBase()); } inline bool inUse() const { - return !(mm_data & NotInUse); + const HeapItem *h = reinterpret_cast(this); + Chunk *c = h->chunk(); + Q_ASSERT(!Chunk::testBit(c->extendsBitmap, h - c->realBase())); + return Chunk::testBit(c->objectBitmap, h - c->realBase()); } Base *nextFree() { diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 3b61273757..e43952bd01 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -190,6 +190,7 @@ Chunk *MemorySegment::allocate(size_t size) pageReservation.commit(candidate, size); for (uint i = 0; i < requiredChunks; ++i) setBit(candidate - base + i); + DEBUG << "allocated chunk " << candidate << hex << size; return candidate; } } @@ -245,6 +246,125 @@ void ChunkAllocator::free(Chunk *chunk, size_t size) } +void Chunk::sweep() +{ + // DEBUG << "sweeping chunk" << this << (*freeList); + HeapItem *o = realBase(); + for (uint i = 0; i < Chunk::EntriesInBitmap; ++i) { + Q_ASSERT((grayBitmap[i] | blackBitmap[i]) == blackBitmap[i]); // check that we don't have gray only objects + quintptr toFree = objectBitmap[i] ^ blackBitmap[i]; + Q_ASSERT((toFree & objectBitmap[i]) == toFree); // check all black objects are marked as being used + quintptr e = extendsBitmap[i]; + // DEBUG << hex << " index=" << i << toFree; + while (toFree) { + uint index = qCountTrailingZeroBits(toFree); + quintptr bit = (static_cast(1) << index); + + toFree ^= bit; // mask out freed slot + // DEBUG << " index" << hex << index << toFree; + + // remove all extends slots that have been freed + // this is a bit of bit trickery. + quintptr mask = (bit << 1) - 1; // create a mask of 1's to the right of and up to the current bit + quintptr objmask = e | mask; // or'ing mask with e gives all ones until the end of the current object + quintptr result = objmask + 1; + Q_ASSERT(qCountTrailingZeroBits(result) - index != 0); // ensure we freed something + result |= mask; // ensure we don't clear stuff to the right of the current object + e &= result; + + HeapItem *itemToFree = o + index; + Heap::Base *b = *itemToFree; + if (b->vtable()->destroy) { + b->vtable()->destroy(b); + b->_checkIsDestroyed(); + } + } + objectBitmap[i] = blackBitmap[i]; + blackBitmap[i] = 0; + extendsBitmap[i] = e; + o += Chunk::Bits; + } + // DEBUG << "swept chunk" << this << "freed" << slotsFreed << "slots."; +} + +void Chunk::freeAll() +{ + // DEBUG << "sweeping chunk" << this << (*freeList); + HeapItem *o = realBase(); + for (uint i = 0; i < Chunk::EntriesInBitmap; ++i) { + quintptr toFree = objectBitmap[i]; + quintptr e = extendsBitmap[i]; + // DEBUG << hex << " index=" << i << toFree; + while (toFree) { + uint index = qCountTrailingZeroBits(toFree); + quintptr bit = (static_cast(1) << index); + + toFree ^= bit; // mask out freed slot + // DEBUG << " index" << hex << index << toFree; + + // remove all extends slots that have been freed + // this is a bit of bit trickery. + quintptr mask = (bit << 1) - 1; // create a mask of 1's to the right of and up to the current bit + quintptr objmask = e | mask; // or'ing mask with e gives all ones until the end of the current object + quintptr result = objmask + 1; + Q_ASSERT(qCountTrailingZeroBits(result) - index != 0); // ensure we freed something + result |= mask; // ensure we don't clear stuff to the right of the current object + e &= result; + + HeapItem *itemToFree = o + index; + Heap::Base *b = *itemToFree; + if (b->vtable()->destroy) { + b->vtable()->destroy(b); + b->_checkIsDestroyed(); + } + } + objectBitmap[i] = 0; + blackBitmap[i] = 0; + extendsBitmap[i] = e; + o += Chunk::Bits; + } + // DEBUG << "swept chunk" << this << "freed" << slotsFreed << "slots."; +} + +void Chunk::sortIntoBins(HeapItem **bins, uint nBins) +{ + HeapItem *base = realBase(); +#if QT_POINTER_SIZE == 8 + const int start = 0; +#else + const int start = 1; +#endif + for (int i = start; i < EntriesInBitmap; ++i) { + quintptr usedSlots = (objectBitmap[i]|extendsBitmap[i]); +#if QT_POINTER_SIZE == 8 + if (!i) + usedSlots |= (static_cast(1) << (HeaderSize/SlotSize)) - 1; +#endif + uint index = qCountTrailingZeroBits(usedSlots + 1); + if (index == Bits) + continue; + uint freeStart = i*Bits + index; + usedSlots &= ~((static_cast(1) << index) - 1); + while (i < EntriesInBitmap && !usedSlots) { + ++i; + usedSlots = (objectBitmap[i]|extendsBitmap[i]); + } + if (i == EntriesInBitmap) + usedSlots = 1; + HeapItem *freeItem = base + freeStart; + + uint freeEnd = i*Bits + qCountTrailingZeroBits(usedSlots); + uint nSlots = freeEnd - freeStart; + Q_ASSERT(freeEnd > freeStart && freeEnd <= NumSlots); + freeItem->freeData.availableSlots = nSlots; + uint bin = qMin(nBins - 1, nSlots); + freeItem->freeData.next = bins[bin]; + bins[bin] = freeItem; + // DEBUG << "binnig item" << freeItem << nSlots << bin << freeItem->freeData.availableSlots; + } +} + + template StackAllocator::StackAllocator(ChunkAllocator *chunkAlloc) : chunkAllocator(chunkAlloc) @@ -288,6 +408,164 @@ void QV4::StackAllocator::prevChunk() { template struct StackAllocator; + +HeapItem *BlockAllocator::allocate(size_t size, bool forceAllocation) { + Q_ASSERT((size % Chunk::SlotSize) == 0); + size_t slotsRequired = size >> Chunk::SlotSizeShift; +#if MM_DEBUG + ++allocations[bin]; +#endif + + HeapItem **last; + + HeapItem *m; + + if (slotsRequired < NumBins - 1) { + m = freeBins[slotsRequired]; + if (m) { + freeBins[slotsRequired] = m->freeData.next; + goto done; + } + } +#if 0 + for (uint b = bin + 1; b < NumBins - 1; ++b) { + if ((m = freeBins[b])) { + Q_ASSERT(binForSlots(m->freeData.availableSlots) == b); + freeBins[b] = m->freeData.next; + // DEBUG << "looking for empty bin" << bin << "size" << size << "found" << b; + uint remainingSlots = m->freeData.availableSlots - slotsRequired; + // DEBUG << "found free slots of size" << m->freeData.availableSlots << m << "remaining" << remainingSlots; + if (remainingSlots < 2) { + // avoid too much fragmentation and rather mark the memory as used + size += remainingSlots*Chunk::SlotSize; + goto done; + } + HeapItem *remainder = m + slotsRequired; + remainder->freeData.availableSlots = remainingSlots; + uint binForRemainder = binForSlots(remainingSlots); + remainder->freeData.next = freeBins[binForRemainder]; + freeBins[binForRemainder] = remainder; + goto done; + } + } +#endif + if (nFree >= slotsRequired) { + // use bump allocation + Q_ASSERT(nextFree); + m = nextFree; + nextFree += slotsRequired; + nFree -= slotsRequired; + goto done; + } + + // DEBUG << "No matching bin found for item" << size << bin; + // search last bin for a large enough item + last = &freeBins[NumBins - 1]; + while ((m = *last)) { + if (m->freeData.availableSlots >= slotsRequired) { + *last = m->freeData.next; // take it out of the list + + size_t remainingSlots = m->freeData.availableSlots - slotsRequired; + // DEBUG << "found large free slots of size" << m->freeData.availableSlots << m << "remaining" << remainingSlots; + if (remainingSlots < 2) { + // avoid too much fragmentation and rather mark the memory as used + size += remainingSlots*Chunk::SlotSize; + goto done; + } + HeapItem *remainder = m + slotsRequired; + if (remainingSlots >= 2*NumBins) { + if (nFree) { + size_t bin = binForSlots(nFree); + nextFree->freeData.next = freeBins[bin]; + nextFree->freeData.availableSlots = nFree; + freeBins[bin] = nextFree; + } + nextFree = remainder; + nFree = remainingSlots; + } else { + remainder->freeData.availableSlots = remainingSlots; + size_t binForRemainder = binForSlots(remainingSlots); + remainder->freeData.next = freeBins[binForRemainder]; + freeBins[binForRemainder] = remainder; + } + goto done; + } + last = &m->freeData.next; + } + + if (!m) { + if (!forceAllocation) + return 0; + Chunk *newChunk = chunkAllocator->allocate(); + chunks.push_back(newChunk); + nextFree = newChunk->first(); + nFree = Chunk::AvailableSlots; + m = nextFree; + nextFree += slotsRequired; + nFree -= slotsRequired; + } + +done: + m->setAllocatedSlots(slotsRequired); + // DEBUG << " " << hex << m->chunk() << m->chunk()->objectBitmap[0] << m->chunk()->extendsBitmap[0] << (m - m->chunk()->realBase()); + return m; +} + +void BlockAllocator::sweep() +{ + nextFree = 0; + nFree = 0; + memset(freeBins, 0, sizeof(freeBins)); + +// qDebug() << "BlockAlloc: sweep"; + usedSlotsAfterLastSweep = 0; + for (auto c : chunks) { + c->sweep(); + c->sortIntoBins(freeBins, NumBins); +// qDebug() << "used slots in chunk" << c << ":" << c->nUsedSlots(); + usedSlotsAfterLastSweep += c->nUsedSlots(); + } +} + +void BlockAllocator::freeAll() +{ + for (auto c : chunks) { + c->freeAll(); + chunkAllocator->free(c); + } +} + +#if MM_DEBUG +void BlockAllocator::stats() { + DEBUG << "MM stats:"; + QString s; + for (int i = 0; i < 10; ++i) { + uint c = 0; + HeapItem *item = freeBins[i]; + while (item) { + ++c; + item = item->freeData.next; + } + s += QString::number(c) + QLatin1String(", "); + } + HeapItem *item = freeBins[NumBins - 1]; + uint c = 0; + while (item) { + ++c; + item = item->freeData.next; + } + s += QLatin1String("..., ") + QString::number(c); + DEBUG << "bins:" << s; + QString a; + for (int i = 0; i < 10; ++i) + a += QString::number(allocations[i]) + QLatin1String(", "); + a += QLatin1String("..., ") + QString::number(allocations[NumBins - 1]); + DEBUG << "allocs:" << a; + memset(allocations, 0, sizeof(allocations)); +} +#endif + + HeapItem *HugeItemAllocator::allocate(size_t size) { Chunk *c = chunkAllocator->allocate(size); chunks.push_back(HugeChunk{c, size}); @@ -329,128 +607,33 @@ void HugeItemAllocator::freeAll() struct MemoryManager::Data { - const size_t pageSize; - - struct ChunkHeader { - Heap::Base freeItems; - ChunkHeader *nextNonFull; - char *itemStart; - char *itemEnd; - unsigned itemSize; - }; - ExecutionEngine *engine; - std::vector heapChunks; std::size_t unmanagedHeapSize; // the amount of bytes of heap that is not managed by the memory manager, but which is held onto by managed items. std::size_t unmanagedHeapSizeGCLimit; - enum { MaxItemSize = 512 }; - ChunkHeader *nonFullChunks[MaxItemSize/16]; - uint nChunks[MaxItemSize/16]; - uint availableItems[MaxItemSize/16]; - uint allocCount[MaxItemSize/16]; - int totalItems; - int totalAlloc; - bool gcBlocked; bool aggressiveGC; bool gcStats; - bool unused; // suppress padding warning - - // statistics: -#ifdef DETAILED_MM_STATS - QVector allocSizeCounters; -#endif // DETAILED_MM_STATS Data() - : pageSize(WTF::pageSize()) - , engine(0) + : engine(0) , unmanagedHeapSize(0) , unmanagedHeapSizeGCLimit(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT) - , totalItems(0) - , totalAlloc(0) , gcBlocked(false) , aggressiveGC(!qEnvironmentVariableIsEmpty("QV4_MM_AGGRESSIVE_GC")) , gcStats(!qEnvironmentVariableIsEmpty(QV4_MM_STATS)) { - memset(nonFullChunks, 0, sizeof(nonFullChunks)); - memset(nChunks, 0, sizeof(nChunks)); - memset(availableItems, 0, sizeof(availableItems)); - memset(allocCount, 0, sizeof(allocCount)); } - ~Data() - { - for (std::vector::iterator i = heapChunks.begin(), ei = heapChunks.end(); i != ei; ++i) { - Q_V4_PROFILE_DEALLOC(engine, i->size(), Profiling::HeapPage); - i->deallocate(); - } - } }; -namespace { - -bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, ExecutionEngine *engine) -{ - bool isEmpty = true; - Heap::Base *tail = &header->freeItems; -// qDebug("chunkStart @ %p, size=%x, pos=%x", header->itemStart, header->itemSize, header->itemSize>>4); -#ifdef V4_USE_VALGRIND - VALGRIND_DISABLE_ERROR_REPORTING; -#endif - for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) { - Heap::Base *m = reinterpret_cast(item); -// qDebug("chunk @ %p, in use: %s, mark bit: %s", -// item, (m->inUse() ? "yes" : "no"), (m->isMarked() ? "true" : "false")); - - Q_ASSERT(qintptr(item) % 16 == 0); - - if (m->isMarked()) { - Q_ASSERT(m->inUse()); - m->clearMarkBit(); - isEmpty = false; - ++(*itemsInUse); - } else { - if (m->inUse()) { -// qDebug() << "-- collecting it." << m << tail << m->nextFree(); -#ifdef V4_USE_VALGRIND - VALGRIND_ENABLE_ERROR_REPORTING; -#endif - if (m->vtable()->destroy) { - m->vtable()->destroy(m); - m->_checkIsDestroyed(); - } - - memset(m, 0, sizeof(Heap::Base)); -#ifdef V4_USE_VALGRIND - VALGRIND_DISABLE_ERROR_REPORTING; - VALGRIND_MEMPOOL_FREE(engine->memoryManager, m); -#endif -#ifdef V4_USE_HEAPTRACK - heaptrack_report_free(m); -#endif - Q_V4_PROFILE_DEALLOC(engine, header->itemSize, Profiling::SmallItem); - ++(*itemsInUse); - } - // Relink all free blocks to rewrite references to any released chunk. - tail->setNextFree(m); - tail = m; - } - } - tail->setNextFree(0); -#ifdef V4_USE_VALGRIND - VALGRIND_ENABLE_ERROR_REPORTING; -#endif - return isEmpty; -} - -} // namespace MemoryManager::MemoryManager(ExecutionEngine *engine) : engine(engine) , chunkAllocator(new ChunkAllocator) , stackAllocator(chunkAllocator) + , blockAllocator(chunkAllocator) , hugeItemAllocator(chunkAllocator) , m_d(new Data) , m_persistentValues(new PersistentValueStorage(engine)) @@ -460,20 +643,15 @@ MemoryManager::MemoryManager(ExecutionEngine *engine) VALGRIND_CREATE_MEMPOOL(this, 0, true); #endif m_d->engine = engine; + + // ### initialize chunkList and stringChunks } -Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize) +Heap::Base *MemoryManager::allocString(std::size_t unmanagedSize) { if (m_d->aggressiveGC) runGC(); -#ifdef DETAILED_MM_STATS - willAllocate(size); -#endif // DETAILED_MM_STATS - - Q_ASSERT(size >= 16); - Q_ASSERT(size % 16 == 0); -// qDebug() << "unmanagedHeapSize:" << m_d->unmanagedHeapSize << "limit:" << m_d->unmanagedHeapSizeGCLimit << "unmanagedSize:" << unmanagedSize; m_d->unmanagedHeapSize += unmanagedSize; bool didGCRun = false; if (m_d->unmanagedHeapSize > m_d->unmanagedHeapSizeGCLimit) { @@ -488,84 +666,39 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize didGCRun = true; } - size_t pos = size >> 4; - - // doesn't fit into a small bucket - if (size >= MemoryManager::Data::MaxItemSize) { - HeapItem *item = hugeItemAllocator.allocate(size); - return *item; + HeapItem *m = blockAllocator.allocate(align(sizeof(Heap::String))); + if (!m) { + if (!didGCRun && shouldRunGC()) + runGC(); + m = blockAllocator.allocate(align(sizeof(Heap::String)), true); } - Heap::Base *m = 0; - Data::ChunkHeader *header = m_d->nonFullChunks[pos]; - if (header) { - m = header->freeItems.nextFree(); - goto found; - } + return *m; +} - // try to free up space, otherwise allocate - if (!didGCRun && m_d->allocCount[pos] > (m_d->availableItems[pos] >> 1) && m_d->totalAlloc > (m_d->totalItems >> 1) && !m_d->aggressiveGC) { +Heap::Base *MemoryManager::allocData(std::size_t size) +{ + if (m_d->aggressiveGC) runGC(); - header = m_d->nonFullChunks[pos]; - if (header) { - m = header->freeItems.nextFree(); - goto found; - } - } +#ifdef DETAILED_MM_STATS + willAllocate(size); +#endif // DETAILED_MM_STATS - // no free item available, allocate a new chunk - { - std::size_t allocSize = QV4::Chunk::ChunkSize; - Q_V4_PROFILE_ALLOC(engine, allocSize, Profiling::HeapPage); - PageAllocation allocation = PageAllocation::allocate(allocSize, OSAllocator::JSGCHeapPages); - m_d->heapChunks.push_back(allocation); - - header = reinterpret_cast(allocation.base()); - Q_ASSERT(size <= UINT_MAX); - header->itemSize = unsigned(size); - header->itemStart = reinterpret_cast(allocation.base()) + roundUpToMultipleOf(16, sizeof(Data::ChunkHeader)); - header->itemEnd = reinterpret_cast(allocation.base()) + allocation.size() - header->itemSize; - - header->nextNonFull = m_d->nonFullChunks[pos]; - m_d->nonFullChunks[pos] = header; - - Heap::Base *last = &header->freeItems; - for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) { - Heap::Base *o = reinterpret_cast(item); - last->setNextFree(o); - last = o; + Q_ASSERT(size >= Chunk::SlotSize); + Q_ASSERT(size % Chunk::SlotSize == 0); - } - last->setNextFree(0); - m = header->freeItems.nextFree(); - Q_ASSERT(header->itemEnd >= header->itemStart); - const size_t increase = quintptr(header->itemEnd - header->itemStart) / header->itemSize; - m_d->availableItems[pos] += uint(increase); - m_d->totalItems += int(increase); -#ifdef V4_USE_VALGRIND - VALGRIND_MAKE_MEM_NOACCESS(allocation.base(), allocSize); - VALGRIND_MEMPOOL_ALLOC(this, header, sizeof(Data::ChunkHeader)); -#endif -#ifdef V4_USE_HEAPTRACK - heaptrack_report_alloc(header, sizeof(Data::ChunkHeader)); -#endif - } +// qDebug() << "unmanagedHeapSize:" << m_d->unmanagedHeapSize << "limit:" << m_d->unmanagedHeapSizeGCLimit << "unmanagedSize:" << unmanagedSize; - found: -#ifdef V4_USE_VALGRIND - VALGRIND_MEMPOOL_ALLOC(this, m, size); -#endif -#ifdef V4_USE_HEAPTRACK - heaptrack_report_alloc(m, size); -#endif - Q_V4_PROFILE_ALLOC(engine, size, Profiling::SmallItem); + if (size > Chunk::DataSize) + return *hugeItemAllocator.allocate(size); - ++m_d->allocCount[pos]; - ++m_d->totalAlloc; - header->freeItems.setNextFree(m->nextFree()); - if (!header->freeItems.nextFree()) - m_d->nonFullChunks[pos] = header->nextNonFull; - return m; + HeapItem *m = blockAllocator.allocate(size); + if (!m) { + if (shouldRunGC()) + runGC(); + m = blockAllocator.allocate(size, true); + } + return *m; } static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase) @@ -669,58 +802,20 @@ void MemoryManager::sweep(bool lastSweep) } } - bool *chunkIsEmpty = static_cast(alloca(m_d->heapChunks.size() * sizeof(bool))); - uint itemsInUse[MemoryManager::Data::MaxItemSize/16]; - memset(itemsInUse, 0, sizeof(itemsInUse)); - memset(m_d->nonFullChunks, 0, sizeof(m_d->nonFullChunks)); - - for (size_t i = 0; i < m_d->heapChunks.size(); ++i) { - Data::ChunkHeader *header = reinterpret_cast(m_d->heapChunks[i].base()); - chunkIsEmpty[i] = sweepChunk(header, &itemsInUse[header->itemSize >> 4], engine); - } - - std::vector::iterator chunkIter = m_d->heapChunks.begin(); - for (size_t i = 0; i < m_d->heapChunks.size(); ++i) { - Q_ASSERT(chunkIter != m_d->heapChunks.end()); - Data::ChunkHeader *header = reinterpret_cast(chunkIter->base()); - const size_t pos = header->itemSize >> 4; - Q_ASSERT(header->itemEnd >= header->itemStart); - const size_t decrease = quintptr(header->itemEnd - header->itemStart) / header->itemSize; - - // Release that chunk if it could have been spared since the last GC run without any difference. - if (chunkIsEmpty[i] && m_d->availableItems[pos] - decrease >= itemsInUse[pos]) { - Q_V4_PROFILE_DEALLOC(engine, chunkIter->size(), Profiling::HeapPage); -#ifdef V4_USE_VALGRIND - VALGRIND_MEMPOOL_FREE(this, header); -#endif -#ifdef V4_USE_HEAPTRACK - heaptrack_report_free(header); -#endif - --m_d->nChunks[pos]; - m_d->availableItems[pos] -= uint(decrease); - m_d->totalItems -= int(decrease); - chunkIter->deallocate(); - chunkIter = m_d->heapChunks.erase(chunkIter); - continue; - } else if (header->freeItems.nextFree()) { - header->nextNonFull = m_d->nonFullChunks[pos]; - m_d->nonFullChunks[pos] = header; - } - ++chunkIter; - } - + blockAllocator.sweep(); hugeItemAllocator.sweep(); +} - // some execution contexts are allocated on the stack, make sure we clear their markBit as well - if (!lastSweep) { - QV4::ExecutionContext *ctx = engine->currentContext; - while (ctx) { - ctx->d()->clearMarkBit(); - ctx = engine->parentContext(ctx); - } - } +bool MemoryManager::shouldRunGC() const +{ + size_t total = blockAllocator.totalSlots(); + size_t usedSlots = blockAllocator.usedSlotsAfterLastSweep; + if (total > MinSlotsGCLimit && usedSlots * GCOverallocation < total * 100) + return true; + return false; } + void MemoryManager::runGC() { if (m_d->gcBlocked) { @@ -731,8 +826,10 @@ void MemoryManager::runGC() QScopedValueRollback gcBlocker(m_d->gcBlocked, true); if (!m_d->gcStats) { +// uint oldUsed = m_d->allocator.usedMem(); mark(); sweep(); +// DEBUG << "RUN GC: allocated:" << m_d->allocator.allocatedMem() << "used before" << oldUsed << "used now" << m_d->allocator.usedMem(); } else { const size_t totalMem = getAllocatedMem(); @@ -742,7 +839,6 @@ void MemoryManager::runGC() qint64 markTime = t.restart(); const size_t usedBefore = getUsedMem(); const size_t largeItemsBefore = getLargeItemsMem(); - size_t chunksBefore = m_d->heapChunks.size(); sweep(); const size_t usedAfter = getUsedMem(); const size_t largeItemsAfter = getLargeItemsMem(); @@ -751,42 +847,25 @@ void MemoryManager::runGC() qDebug() << "========== GC =========="; qDebug() << "Marked object in" << markTime << "ms."; qDebug() << "Sweeped object in" << sweepTime << "ms."; - qDebug() << "Allocated" << totalMem << "bytes in" << m_d->heapChunks.size() << "chunks."; + qDebug() << "Allocated" << totalMem << "bytes"; qDebug() << "Used memory before GC:" << usedBefore; qDebug() << "Used memory after GC:" << usedAfter; qDebug() << "Freed up bytes:" << (usedBefore - usedAfter); - qDebug() << "Released chunks:" << (chunksBefore - m_d->heapChunks.size()); qDebug() << "Large item memory before GC:" << largeItemsBefore; qDebug() << "Large item memory after GC:" << largeItemsAfter; qDebug() << "Large item memory freed up:" << (largeItemsBefore - largeItemsAfter); qDebug() << "======== End GC ========"; } - - memset(m_d->allocCount, 0, sizeof(m_d->allocCount)); - m_d->totalAlloc = 0; } size_t MemoryManager::getUsedMem() const { - size_t usedMem = 0; - for (std::vector::const_iterator i = m_d->heapChunks.cbegin(), ei = m_d->heapChunks.cend(); i != ei; ++i) { - Data::ChunkHeader *header = reinterpret_cast(i->base()); - for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) { - Heap::Base *m = reinterpret_cast(item); - Q_ASSERT(qintptr(item) % 16 == 0); - if (m->inUse()) - usedMem += header->itemSize; - } - } - return usedMem; + return blockAllocator.usedMem(); } size_t MemoryManager::getAllocatedMem() const { - size_t total = 0; - for (size_t i = 0; i < m_d->heapChunks.size(); ++i) - total += m_d->heapChunks.at(i).size(); - return total; + return blockAllocator.allocatedMem() + hugeItemAllocator.usedMem(); } size_t MemoryManager::getLargeItemsMem() const @@ -816,7 +895,6 @@ MemoryManager::~MemoryManager() } - void MemoryManager::dumpStats() const { #ifdef DETAILED_MM_STATS diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index 84769f33ba..b6259092e1 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -116,6 +116,57 @@ struct StackAllocator { uint currentChunk = 0; }; +struct BlockAllocator { + BlockAllocator(ChunkAllocator *chunkAllocator) + : chunkAllocator(chunkAllocator) + { + memset(freeBins, 0, sizeof(freeBins)); +#if MM_DEBUG + memset(allocations, 0, sizeof(allocations)); +#endif + } + + enum { NumBins = 8 }; + + static inline size_t binForSlots(size_t nSlots) { + return nSlots >= NumBins ? NumBins - 1 : nSlots; + } + +#if MM_DEBUG + void stats(); +#endif + + HeapItem *allocate(size_t size, bool forceAllocation = false); + + size_t totalSlots() const { + return Chunk::AvailableSlots*chunks.size(); + } + + size_t allocatedMem() const { + return chunks.size()*Chunk::DataSize; + } + size_t usedMem() const { + uint used = 0; + for (auto c : chunks) + used += c->nUsedSlots()*Chunk::SlotSize; + return used; + } + + void sweep(); + void freeAll(); + + // bump allocations + HeapItem *nextFree = 0; + size_t nFree = 0; + size_t usedSlotsAfterLastSweep = 0; + HeapItem *freeBins[NumBins]; + ChunkAllocator *chunkAllocator; + std::vector chunks; +#if MM_DEBUG + uint allocations[NumBins]; +#endif +}; + struct HugeItemAllocator { HugeItemAllocator(ChunkAllocator *chunkAllocator) : chunkAllocator(chunkAllocator) @@ -155,7 +206,7 @@ public: // TODO: this is only for 64bit (and x86 with SSE/AVX), so exend it for other architectures to be slightly more efficient (meaning, align on 8-byte boundaries). // Note: all occurrences of "16" in alloc/dealloc are also due to the alignment. - static inline std::size_t align(std::size_t size) + Q_DECL_CONSTEXPR static inline std::size_t align(std::size_t size) { return (size + Chunk::SlotSize - 1) & ~(Chunk::SlotSize - 1); } QV4::Heap::CallContext *allocSimpleCallContext() @@ -164,11 +215,11 @@ public: { stackAllocator.free(); } template - inline typename ManagedType::Data *allocManaged(std::size_t size, std::size_t unmanagedSize = 0) + inline typename ManagedType::Data *allocManaged(std::size_t size) { V4_ASSERT_IS_TRIVIAL(typename ManagedType::Data) size = align(size); - Heap::Base *o = allocData(size, unmanagedSize); + Heap::Base *o = allocData(size); memset(o, 0, size); o->setVtable(ManagedType::staticVTable()); return static_cast(o); @@ -202,10 +253,11 @@ public: template typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1) { - Scope scope(engine); - Scoped t(scope, allocManaged(sizeof(typename ManagedType::Data), unmanagedSize)); - t->d_unchecked()->init(this, arg1); - return t->d(); + typename ManagedType::Data *o = reinterpret_cast(allocString(unmanagedSize)); + memset(o, 0, sizeof(sizeof(typename ManagedType::Data))); + o->setVtable(ManagedType::staticVTable()); + o->init(this, arg1); + return o; } template @@ -379,8 +431,8 @@ public: protected: /// expects size to be aligned - // TODO: try to inline - Heap::Base *allocData(std::size_t size, std::size_t unmanagedSize); + Heap::Base *allocString(std::size_t unmanagedSize); + Heap::Base *allocData(std::size_t size); #ifdef DETAILED_MM_STATS void willAllocate(std::size_t size); @@ -390,11 +442,13 @@ private: void collectFromJSStack() const; void mark(); void sweep(bool lastSweep = false); + bool shouldRunGC() const; public: QV4::ExecutionEngine *engine; ChunkAllocator *chunkAllocator; StackAllocator stackAllocator; + BlockAllocator blockAllocator; HugeItemAllocator hugeItemAllocator; QScopedPointer m_d; PersistentValueStorage *m_persistentValues; diff --git a/src/qml/memory/qv4mmdefs_p.h b/src/qml/memory/qv4mmdefs_p.h index 4bfbfadde6..588ae21ee0 100644 --- a/src/qml/memory/qv4mmdefs_p.h +++ b/src/qml/memory/qv4mmdefs_p.h @@ -131,6 +131,8 @@ struct Chunk { } static void setBits(quintptr *bitmap, size_t index, size_t nBits) { // Q_ASSERT(index >= HeaderSize/SlotSize && index + nBits <= ChunkSize/SlotSize); + if (!nBits) + return; bitmap += index >> BitShift; index &= (Bits - 1); while (1) { @@ -171,6 +173,11 @@ struct Chunk { } return usedSlots; } + + void sweep(); + void freeAll(); + + void sortIntoBins(HeapItem **bins, uint nBins); }; struct HeapItem { @@ -209,7 +216,7 @@ struct HeapItem { void setAllocatedSlots(size_t nSlots) { // Q_ASSERT(size && !(size % sizeof(HeapItem))); Chunk *c = chunk(); - uint index = this - c->realBase(); + size_t index = this - c->realBase(); // Q_ASSERT(!Chunk::testBit(c->objectBitmap, index)); Chunk::setBit(c->objectBitmap, index); Chunk::setBits(c->extendsBitmap, index + 1, nSlots - 1); -- cgit v1.2.3 From 49f43a9f889a0697efb4a90bbce2ccaa44532c92 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 21 Dec 2016 17:22:57 +0100 Subject: Cleanup Heap::Base Since the markbit is not stored in line anymore, we can now simply store the pointer to the vtable in the object. Change-Id: I81b616c825dd4f3f2140838daab1f62bd6ecc812 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4context.cpp | 1 - src/qml/memory/qv4heap_p.h | 24 +++--------------------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 0954d621a6..486447f10a 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -99,7 +99,6 @@ Heap::CallContext *Heap::CallContext::createSimpleContext(ExecutionEngine *v4) { Heap::CallContext *ctxt = v4->memoryManager->allocSimpleCallContext(); memset(ctxt, 0, sizeof(Heap::CallContext)); - ctxt->mm_data = 0; ctxt->setVtable(QV4::CallContext::staticVTable()); ctxt->init(v4); return ctxt; diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h index f5172ec83c..8285ef4de7 100644 --- a/src/qml/memory/qv4heap_p.h +++ b/src/qml/memory/qv4heap_p.h @@ -91,24 +91,13 @@ namespace Heap { struct Q_QML_EXPORT Base { void *operator new(size_t) = delete; - quintptr mm_data; // vtable and markbit + const VTable *vt; inline ReturnedValue asReturnedValue() const; inline void mark(QV4::ExecutionEngine *engine); - enum { - MarkBit = 0x1, - NotInUse = 0x2, - PointerMask = ~0x3 - }; - - void setVtable(const VTable *v) { - Q_ASSERT(!(mm_data & MarkBit)); - mm_data = reinterpret_cast(v); - } - VTable *vtable() const { - return reinterpret_cast(mm_data & PointerMask); - } + void setVtable(const VTable *v) { vt = v; } + const VTable *vtable() const { return vt; } inline bool isMarked() const { const HeapItem *h = reinterpret_cast(this); Chunk *c = h->chunk(); @@ -129,13 +118,6 @@ struct Q_QML_EXPORT Base { return Chunk::testBit(c->objectBitmap, h - c->realBase()); } - Base *nextFree() { - return reinterpret_cast(mm_data & PointerMask); - } - void setNextFree(Base *m) { - mm_data = (reinterpret_cast(m) | NotInUse); - } - void *operator new(size_t, Managed *m) { return m; } void *operator new(size_t, Heap::Base *m) { return m; } void operator delete(void *, Heap::Base *) {} -- cgit v1.2.3 From 8acf7385f341752984db280773f167e405b8bc12 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 3 Jan 2017 12:06:25 +0100 Subject: Get rid of MemoryManager::Data Inline the few remaining members into the MemoryManager class itself. Change-Id: If5fef74581daa89df3e8cc237329c27395ce2289 Reviewed-by: Simon Hausmann --- src/qml/memory/qv4mm.cpp | 70 ++++++++++++++---------------------------------- src/qml/memory/qv4mm_p.h | 15 +++++++---- 2 files changed, 30 insertions(+), 55 deletions(-) diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index e43952bd01..b07ca747cd 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -605,64 +605,39 @@ void HugeItemAllocator::freeAll() } -struct MemoryManager::Data -{ - ExecutionEngine *engine; - - std::size_t unmanagedHeapSize; // the amount of bytes of heap that is not managed by the memory manager, but which is held onto by managed items. - std::size_t unmanagedHeapSizeGCLimit; - - bool gcBlocked; - bool aggressiveGC; - bool gcStats; - - Data() - : engine(0) - , unmanagedHeapSize(0) - , unmanagedHeapSizeGCLimit(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT) - , gcBlocked(false) - , aggressiveGC(!qEnvironmentVariableIsEmpty("QV4_MM_AGGRESSIVE_GC")) - , gcStats(!qEnvironmentVariableIsEmpty(QV4_MM_STATS)) - { - } - -}; - - MemoryManager::MemoryManager(ExecutionEngine *engine) : engine(engine) , chunkAllocator(new ChunkAllocator) , stackAllocator(chunkAllocator) , blockAllocator(chunkAllocator) , hugeItemAllocator(chunkAllocator) - , m_d(new Data) , m_persistentValues(new PersistentValueStorage(engine)) , m_weakValues(new PersistentValueStorage(engine)) + , unmanagedHeapSizeGCLimit(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT) + , aggressiveGC(!qEnvironmentVariableIsEmpty("QV4_MM_AGGRESSIVE_GC")) + , gcStats(!qEnvironmentVariableIsEmpty(QV4_MM_STATS)) { #ifdef V4_USE_VALGRIND VALGRIND_CREATE_MEMPOOL(this, 0, true); #endif - m_d->engine = engine; - - // ### initialize chunkList and stringChunks } Heap::Base *MemoryManager::allocString(std::size_t unmanagedSize) { - if (m_d->aggressiveGC) + if (aggressiveGC) runGC(); - m_d->unmanagedHeapSize += unmanagedSize; + unmanagedHeapSize += unmanagedSize; bool didGCRun = false; - if (m_d->unmanagedHeapSize > m_d->unmanagedHeapSizeGCLimit) { + if (unmanagedHeapSize > unmanagedHeapSizeGCLimit) { runGC(); - if (3*m_d->unmanagedHeapSizeGCLimit <= 4*m_d->unmanagedHeapSize) + if (3*unmanagedHeapSizeGCLimit <= 4*unmanagedHeapSize) // more than 75% full, raise limit - m_d->unmanagedHeapSizeGCLimit = std::max(m_d->unmanagedHeapSizeGCLimit, m_d->unmanagedHeapSize) * 2; - else if (m_d->unmanagedHeapSize * 4 <= m_d->unmanagedHeapSizeGCLimit) + unmanagedHeapSizeGCLimit = std::max(unmanagedHeapSizeGCLimit, unmanagedHeapSize) * 2; + else if (unmanagedHeapSize * 4 <= unmanagedHeapSizeGCLimit) // less than 25% full, lower limit - m_d->unmanagedHeapSizeGCLimit = qMax(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT, m_d->unmanagedHeapSizeGCLimit/2); + unmanagedHeapSizeGCLimit = qMax(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT, unmanagedHeapSizeGCLimit/2); didGCRun = true; } @@ -678,7 +653,7 @@ Heap::Base *MemoryManager::allocString(std::size_t unmanagedSize) Heap::Base *MemoryManager::allocData(std::size_t size) { - if (m_d->aggressiveGC) + if (aggressiveGC) runGC(); #ifdef DETAILED_MM_STATS willAllocate(size); @@ -687,7 +662,7 @@ Heap::Base *MemoryManager::allocData(std::size_t size) Q_ASSERT(size >= Chunk::SlotSize); Q_ASSERT(size % Chunk::SlotSize == 0); -// qDebug() << "unmanagedHeapSize:" << m_d->unmanagedHeapSize << "limit:" << m_d->unmanagedHeapSizeGCLimit << "unmanagedSize:" << unmanagedSize; +// qDebug() << "unmanagedHeapSize:" << unmanagedHeapSize << "limit:" << unmanagedHeapSizeGCLimit << "unmanagedSize:" << unmanagedSize; if (size > Chunk::DataSize) return *hugeItemAllocator.allocate(size); @@ -818,18 +793,18 @@ bool MemoryManager::shouldRunGC() const void MemoryManager::runGC() { - if (m_d->gcBlocked) { + if (gcBlocked) { // qDebug() << "Not running GC."; return; } - QScopedValueRollback gcBlocker(m_d->gcBlocked, true); + QScopedValueRollback gcBlocker(gcBlocked, true); - if (!m_d->gcStats) { -// uint oldUsed = m_d->allocator.usedMem(); + if (!gcStats) { +// uint oldUsed = allocator.usedMem(); mark(); sweep(); -// DEBUG << "RUN GC: allocated:" << m_d->allocator.allocatedMem() << "used before" << oldUsed << "used now" << m_d->allocator.usedMem(); +// DEBUG << "RUN GC: allocated:" << allocator.allocatedMem() << "used before" << oldUsed << "used now" << allocator.usedMem(); } else { const size_t totalMem = getAllocatedMem(); @@ -873,11 +848,6 @@ size_t MemoryManager::getLargeItemsMem() const return hugeItemAllocator.usedMem(); } -void MemoryManager::changeUnmanagedHeapSizeUsage(qptrdiff delta) -{ - m_d->unmanagedHeapSize += delta; -} - MemoryManager::~MemoryManager() { delete m_persistentValues; @@ -901,8 +871,8 @@ void MemoryManager::dumpStats() const std::cerr << "=================" << std::endl; std::cerr << "Allocation stats:" << std::endl; std::cerr << "Requests for each chunk size:" << std::endl; - for (int i = 0; i < m_d->allocSizeCounters.size(); ++i) { - if (unsigned count = m_d->allocSizeCounters[i]) { + for (int i = 0; i < allocSizeCounters.size(); ++i) { + if (unsigned count = allocSizeCounters[i]) { std::cerr << "\t" << (i << 4) << " bytes chunks: " << count << std::endl; } } @@ -913,7 +883,7 @@ void MemoryManager::dumpStats() const void MemoryManager::willAllocate(std::size_t size) { unsigned alignedSize = (size + 15) >> 4; - QVector &counters = m_d->allocSizeCounters; + QVector &counters = allocSizeCounters; if ((unsigned) counters.size() < alignedSize + 1) counters.resize(alignedSize + 1); counters[alignedSize]++; diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index b6259092e1..9cb71e70de 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -197,9 +197,6 @@ class Q_QML_EXPORT MemoryManager { Q_DISABLE_COPY(MemoryManager); -public: - struct Data; - public: MemoryManager(ExecutionEngine *engine); ~MemoryManager(); @@ -427,7 +424,9 @@ public: size_t getAllocatedMem() const; size_t getLargeItemsMem() const; - void changeUnmanagedHeapSizeUsage(qptrdiff delta); // called when a JS object grows itself. Specifically: Heap::String::append + // called when a JS object grows itself. Specifically: Heap::String::append + void changeUnmanagedHeapSizeUsage(qptrdiff delta) { unmanagedHeapSize += delta; } + protected: /// expects size to be aligned @@ -450,10 +449,16 @@ public: StackAllocator stackAllocator; BlockAllocator blockAllocator; HugeItemAllocator hugeItemAllocator; - QScopedPointer m_d; PersistentValueStorage *m_persistentValues; PersistentValueStorage *m_weakValues; QVector m_pendingFreedObjectWrapperValue; + + std::size_t unmanagedHeapSize = 0; // the amount of bytes of heap that is not managed by the memory manager, but which is held onto by managed items. + std::size_t unmanagedHeapSizeGCLimit; + + bool gcBlocked = false; + bool aggressiveGC = false; + bool gcStats = false; }; } -- cgit v1.2.3 From d8c6bf2dc129522f779d2c4ffc698a97b7531f66 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 4 Jan 2017 10:49:23 +0100 Subject: Let allocData/allocString return 0 initialized memory There's no point in having the memset inline. In theory, the compiler could optimize by combining this with later on inline initialization code, in practice this doesn't happen anyway, and we have some options of avoiding or combing the memsets in the allocator. Change-Id: I4502ef947ae235223726269821f9482ad62e1070 Reviewed-by: Simon Hausmann --- src/qml/memory/qv4mm.cpp | 8 ++++++-- src/qml/memory/qv4mm_p.h | 2 -- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index b07ca747cd..4cad197d32 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -627,6 +627,7 @@ Heap::Base *MemoryManager::allocString(std::size_t unmanagedSize) if (aggressiveGC) runGC(); + const uint stringSize = align(sizeof(Heap::String)); unmanagedHeapSize += unmanagedSize; bool didGCRun = false; if (unmanagedHeapSize > unmanagedHeapSizeGCLimit) { @@ -641,13 +642,14 @@ Heap::Base *MemoryManager::allocString(std::size_t unmanagedSize) didGCRun = true; } - HeapItem *m = blockAllocator.allocate(align(sizeof(Heap::String))); + HeapItem *m = blockAllocator.allocate(stringSize); if (!m) { if (!didGCRun && shouldRunGC()) runGC(); - m = blockAllocator.allocate(align(sizeof(Heap::String)), true); + m = blockAllocator.allocate(stringSize, true); } + memset(m, 0, stringSize); return *m; } @@ -673,6 +675,8 @@ Heap::Base *MemoryManager::allocData(std::size_t size) runGC(); m = blockAllocator.allocate(size, true); } + + memset(m, 0, size); return *m; } diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index 9cb71e70de..7517328b37 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -217,7 +217,6 @@ public: V4_ASSERT_IS_TRIVIAL(typename ManagedType::Data) size = align(size); Heap::Base *o = allocData(size); - memset(o, 0, size); o->setVtable(ManagedType::staticVTable()); return static_cast(o); } @@ -251,7 +250,6 @@ public: typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1) { typename ManagedType::Data *o = reinterpret_cast(allocString(unmanagedSize)); - memset(o, 0, sizeof(sizeof(typename ManagedType::Data))); o->setVtable(ManagedType::staticVTable()); o->init(this, arg1); return o; -- cgit v1.2.3 From a56809dcfda21363d3c96c39c6075d5d65e116a6 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 4 Jan 2017 12:45:45 +0100 Subject: Get rid of the inline member data in Object Instead allocate a MemberData at the same time as the object if required. Turns out this is faster now, and significantly simplifies some of our internal logic to access member properties. In addition, we can properly setup the inline member size to use the full extent of the memory reserved by the memory manager. This avoid some needless reallocations of MemberData objects. Change-Id: I36daeeaf6df16f2268103662fc78d600b4058ef8 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4internalclass.cpp | 32 +++----------------------------- src/qml/jsruntime/qv4memberdata.cpp | 6 +++--- src/qml/jsruntime/qv4object.cpp | 11 ++--------- src/qml/jsruntime/qv4object_p.h | 6 ++---- src/qml/memory/qv4mm.cpp | 25 ++++++++++++++++++++++++- src/qml/memory/qv4mm_p.h | 17 +++++++---------- 6 files changed, 41 insertions(+), 56 deletions(-) diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index d17da9af0c..bac71b4537 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -128,48 +128,22 @@ InternalClass::InternalClass(const QV4::InternalClass &other) static void insertHoleIntoPropertyData(Object *object, int idx) { - int inlineSize = object->d()->inlineMemberSize; int icSize = object->internalClass()->size; - int from = qMax(idx, inlineSize); + int from = idx; int to = from + 1; - if (from < icSize) { + if (from < icSize) memmove(object->propertyData(to), object->propertyData(from), (icSize - from - 1) * sizeof(Value)); - } - if (from == idx) - return; - if (inlineSize < icSize) - *object->propertyData(inlineSize) = *object->propertyData(inlineSize - 1); - from = idx; - to = from + 1; - if (from < inlineSize - 1) { - memmove(object->propertyData(to), object->propertyData(from), - (inlineSize - from - 1) * sizeof(Value)); - } } static void removeFromPropertyData(Object *object, int idx, bool accessor = false) { - int inlineSize = object->d()->inlineMemberSize; int delta = (accessor ? 2 : 1); int oldSize = object->internalClass()->size + delta; int to = idx; int from = to + delta; - if (from < inlineSize) { - memmove(object->propertyData(to), object->d()->propertyData(from), (inlineSize - from)*sizeof(Value)); - to = inlineSize - delta; - from = inlineSize; - } - if (to < inlineSize && from < oldSize) { - Q_ASSERT(from >= inlineSize); - memcpy(object->propertyData(to), object->d()->propertyData(from), (inlineSize - to)*sizeof(Value)); - to = inlineSize; - from = inlineSize + delta; - } - if (from < oldSize) { - Q_ASSERT(to >= inlineSize && from > to); + if (from < oldSize) memmove(object->propertyData(to), object->d()->propertyData(from), (oldSize - to)*sizeof(Value)); - } } void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index) diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp index d5f75415cc..f2a24f8179 100644 --- a/src/qml/jsruntime/qv4memberdata.cpp +++ b/src/qml/jsruntime/qv4memberdata.cpp @@ -56,12 +56,12 @@ Heap::MemberData *MemberData::allocate(ExecutionEngine *e, uint n, Heap::MemberD { Q_ASSERT(!old || old->size < n); - uint alloc = sizeof(Heap::MemberData) + (n)*sizeof(Value); + size_t alloc = MemoryManager::align(sizeof(Heap::MemberData) + (n - 1)*sizeof(Value)); Heap::MemberData *m = e->memoryManager->allocManaged(alloc); if (old) - memcpy(m, old, sizeof(Heap::MemberData) + old->size * sizeof(Value)); + memcpy(m, old, sizeof(Heap::MemberData) + (old->size - 1)* sizeof(Value)); else m->init(); - m->size = n; + m->size = static_cast((alloc - sizeof(Heap::MemberData) + sizeof(Value))/sizeof(Value)); return m; } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 8acca16dd0..f217e301ac 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -61,9 +61,8 @@ DEFINE_OBJECT_VTABLE(Object); void Object::setInternalClass(InternalClass *ic) { d()->internalClass = ic; - if ((ic->size > d()->inlineMemberSize && !d()->memberData) || - (d()->memberData && d()->memberData->size < ic->size - d()->inlineMemberSize)) - d()->memberData = MemberData::allocate(ic->engine, ic->size - d()->inlineMemberSize, d()->memberData); + if (!d()->memberData || (d()->memberData->size < ic->size)) + d()->memberData = MemberData::allocate(ic->engine, ic->size, d()->memberData); } void Object::getProperty(uint index, Property *p, PropertyAttributes *attrs) const @@ -213,12 +212,6 @@ void Object::markObjects(Heap::Base *that, ExecutionEngine *e) { Heap::Object *o = static_cast(that); - if (o->inlineMemberSize) { - Value *v = o->propertyData(0); - for (uint i = 0; i < o->inlineMemberSize; ++i) - v[i].mark(e); - } - if (o->memberData) o->memberData->mark(e); if (o->arrayData) diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 6c679deb10..65820911db 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -69,11 +69,9 @@ struct Object : Base { void init() { Base::init(); } void destroy() { Base::destroy(); } - const Value *propertyData(uint index) const { if (index < inlineMemberSize) return reinterpret_cast(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; } - Value *propertyData(uint index) { if (index < inlineMemberSize) return reinterpret_cast(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; } + const Value *propertyData(uint index) const { return memberData->data + index; } + Value *propertyData(uint index) { return memberData->data + index; } - uint inlineMemberOffset; - uint inlineMemberSize; InternalClass *internalClass; Pointer prototype; Pointer memberData; diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 4cad197d32..6330ef6038 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -627,7 +627,7 @@ Heap::Base *MemoryManager::allocString(std::size_t unmanagedSize) if (aggressiveGC) runGC(); - const uint stringSize = align(sizeof(Heap::String)); + const size_t stringSize = align(sizeof(Heap::String)); unmanagedHeapSize += unmanagedSize; bool didGCRun = false; if (unmanagedHeapSize > unmanagedHeapSizeGCLimit) { @@ -680,6 +680,29 @@ Heap::Base *MemoryManager::allocData(std::size_t size) return *m; } +Heap::Object *MemoryManager::allocObjectWithMemberData(std::size_t size, uint nMembers) +{ + Heap::Object *o = static_cast(allocData(size)); + + // ### Could optimize this and allocate both in one go through the block allocator + if (nMembers) { + std::size_t memberSize = align(sizeof(Heap::MemberData) + (nMembers - 1)*sizeof(Value)); +// qDebug() << "allocating member data for" << o << nMembers << memberSize; + Heap::Base *m; + if (memberSize > Chunk::DataSize) + m = *hugeItemAllocator.allocate(memberSize); + else + m = *blockAllocator.allocate(memberSize, true); + memset(m, 0, memberSize); + o->memberData = static_cast(m); + o->memberData->setVtable(MemberData::staticVTable()); + o->memberData->size = static_cast((memberSize - sizeof(Heap::MemberData) + sizeof(Value))/sizeof(Value)); + o->memberData->init(); +// qDebug() << " got" << o->memberData << o->memberData->size; + } + return o; +} + static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase) { while (engine->jsStackTop > markBase) { diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index 7517328b37..76017f8148 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -224,26 +224,22 @@ public: template typename ObjectType::Data *allocateObject(InternalClass *ic) { - const int size = (sizeof(typename ObjectType::Data) + (sizeof(Value) - 1)) & ~(sizeof(Value) - 1); - typename ObjectType::Data *o = allocManaged(size + ic->size*sizeof(Value)); + Heap::Object *o = allocObjectWithMemberData(align(sizeof(typename ObjectType::Data)), ic->size); + o->setVtable(ObjectType::staticVTable()); o->internalClass = ic; - o->inlineMemberSize = ic->size; - o->inlineMemberOffset = size/sizeof(Value); - return o; + return static_cast(o); } template typename ObjectType::Data *allocateObject() { InternalClass *ic = ObjectType::defaultInternalClass(engine); - const int size = (sizeof(typename ObjectType::Data) + (sizeof(Value) - 1)) & ~(sizeof(Value) - 1); - typename ObjectType::Data *o = allocManaged(size + ic->size*sizeof(Value)); + Heap::Object *o = allocObjectWithMemberData(align(sizeof(typename ObjectType::Data)), ic->size); + o->setVtable(ObjectType::staticVTable()); Object *prototype = ObjectType::defaultPrototype(engine); o->internalClass = ic; o->prototype = prototype->d(); - o->inlineMemberSize = ic->size; - o->inlineMemberOffset = size/sizeof(Value); - return o; + return static_cast(o); } template @@ -430,6 +426,7 @@ protected: /// expects size to be aligned Heap::Base *allocString(std::size_t unmanagedSize); Heap::Base *allocData(std::size_t size); + Heap::Object *allocObjectWithMemberData(std::size_t size, uint nMembers); #ifdef DETAILED_MM_STATS void willAllocate(std::size_t size); -- cgit v1.2.3 From 1df5fb40b5417995f4121c15392f56a7bb19e0c2 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 4 Jan 2017 13:26:01 +0100 Subject: Improve SimpleArrayData::markObjects Avoid an expensive modulo operation per Value to be marked. Change-Id: Ibe0adcf0fce73ff760a6adf983c746e66f183332 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4arraydata.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index bfeb3d4699..d8a7de5466 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -237,8 +237,14 @@ void ArrayData::ensureAttributes(Object *o) void SimpleArrayData::markObjects(Heap::Base *d, ExecutionEngine *e) { Heap::SimpleArrayData *dd = static_cast(d); - for (uint i = 0; i < dd->len; ++i) - dd->arrayData[dd->mappedIndex(i)].mark(e); + uint end = dd->offset + dd->len; + if (end > dd->alloc) { + for (uint i = 0; i < end - dd->alloc; ++i) + dd->arrayData[i].mark(e); + end = dd->alloc; + } + for (uint i = dd->offset; i < end; ++i) + dd->arrayData[i].mark(e); } ReturnedValue SimpleArrayData::get(const Heap::ArrayData *d, uint index) -- cgit v1.2.3 From 3e67a40860e0cda4cf6118c97e47cbe55aa672d6 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 4 Jan 2017 15:58:58 +0100 Subject: Inline creation of simple call contexts And avoid zero initializing stuff that's already 0 Change-Id: If90a808815b2b735bab661d22cbd498acc96b029 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4context.cpp | 9 +++------ src/qml/jsruntime/qv4context_p.h | 10 ---------- src/qml/jsruntime/qv4functionobject.cpp | 8 ++++---- src/qml/memory/qv4mm_p.h | 11 +++++++++-- 4 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 486447f10a..60b90e4bf0 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -97,10 +97,7 @@ Heap::CallContext *ExecutionContext::newCallContext(Function *function, CallData Heap::CallContext *Heap::CallContext::createSimpleContext(ExecutionEngine *v4) { - Heap::CallContext *ctxt = v4->memoryManager->allocSimpleCallContext(); - memset(ctxt, 0, sizeof(Heap::CallContext)); - ctxt->setVtable(QV4::CallContext::staticVTable()); - ctxt->init(v4); + Heap::CallContext *ctxt = v4->memoryManager->allocSimpleCallContext(v4); return ctxt; } @@ -339,7 +336,7 @@ void QV4::ExecutionContext::simpleCall(Scope &scope, CallData *callData, Functio ExecutionContextSaver ctxSaver(scope); - CallContext::Data *ctx = CallContext::Data::createSimpleContext(scope.engine); + CallContext::Data *ctx = scope.engine->memoryManager->allocSimpleCallContext(scope.engine); ctx->strictMode = function->isStrict(); ctx->callData = callData; @@ -359,7 +356,7 @@ void QV4::ExecutionContext::simpleCall(Scope &scope, CallData *callData, Functio if (function->hasQmlDependencies) QQmlPropertyCapture::registerQmlDependencies(function->compiledFunction, scope); - ctx->freeSimpleCallContext(); + scope.engine->memoryManager->freeSimpleCallContext(); } void ExecutionContext::setProperty(String *name, const Value &value) diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index 996de174b4..bcfee2e1f8 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -109,14 +109,8 @@ struct ExecutionContext : Base { { Base::init(); - callData = nullptr; this->engine = engine; - outer = nullptr; - lookups = nullptr; - constantTable = nullptr; - compilationUnit = nullptr; type = t; - strictMode = false; lineNumber = -1; } @@ -141,10 +135,6 @@ struct CallContext : ExecutionContext { void init(ExecutionEngine *engine, ContextType t = Type_SimpleCallContext) { ExecutionContext::init(engine, t); - function = 0; - v4Function = 0; - locals = 0; - activation = 0; } inline unsigned int formalParameterCount() const; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 1ac0e28a1b..3bbccdba2f 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -484,14 +484,14 @@ void BuiltinFunction::call(const Managed *that, Scope &scope, CallData *callData ExecutionContextSaver ctxSaver(scope); - CallContext::Data *ctx = CallContext::Data::createSimpleContext(v4); + CallContext::Data *ctx = v4->memoryManager->allocSimpleCallContext(v4); ctx->strictMode = f->scope()->strictMode; // ### needed? scope or parent context? ctx->callData = callData; v4->pushContext(ctx); Q_ASSERT(v4->current == ctx); scope.result = f->d()->code(static_cast(v4->currentContext)); - ctx->freeSimpleCallContext(); + v4->memoryManager->freeSimpleCallContext(); } void IndexedBuiltinFunction::call(const Managed *that, Scope &scope, CallData *callData) @@ -506,14 +506,14 @@ void IndexedBuiltinFunction::call(const Managed *that, Scope &scope, CallData *c ExecutionContextSaver ctxSaver(scope); - CallContext::Data *ctx = CallContext::Data::createSimpleContext(v4); + CallContext::Data *ctx = v4->memoryManager->allocSimpleCallContext(v4); ctx->strictMode = f->scope()->strictMode; // ### needed? scope or parent context? ctx->callData = callData; v4->pushContext(ctx); Q_ASSERT(v4->current == ctx); scope.result = f->d()->code(static_cast(v4->currentContext), f->d()->index); - ctx->freeSimpleCallContext(); + v4->memoryManager->freeSimpleCallContext(); } DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction); diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index 76017f8148..00daf8a622 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -206,8 +206,15 @@ public: Q_DECL_CONSTEXPR static inline std::size_t align(std::size_t size) { return (size + Chunk::SlotSize - 1) & ~(Chunk::SlotSize - 1); } - QV4::Heap::CallContext *allocSimpleCallContext() - { return stackAllocator.allocate(); } + QV4::Heap::CallContext *allocSimpleCallContext(QV4::ExecutionEngine *v4) + { + Heap::CallContext *ctxt = stackAllocator.allocate(); + memset(ctxt, 0, sizeof(Heap::CallContext)); + ctxt->setVtable(QV4::CallContext::staticVTable()); + ctxt->init(v4); + return ctxt; + + } void freeSimpleCallContext() { stackAllocator.free(); } -- cgit v1.2.3 From c2a4277ae5c60a7b7f1e2a083a89ae4e528794c5 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 5 Jan 2017 18:48:20 +0100 Subject: Speed up invocation of builtin functions Completely avoid creation of a CallContext for those methods, as we don't need it. Change-Id: Iff1a38fd3c7e846df6ec0374cb7b3fb8f1b4de3a Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4arrayobject.cpp | 675 ++++++++++++++++---------------- src/qml/jsruntime/qv4arrayobject_p.h | 48 +-- src/qml/jsruntime/qv4functionobject.cpp | 37 +- src/qml/jsruntime/qv4functionobject_p.h | 24 +- src/qml/jsruntime/qv4object.cpp | 21 + src/qml/jsruntime/qv4object_p.h | 4 + src/qml/jsruntime/qv4objectproto.cpp | 412 ++++++++++--------- src/qml/jsruntime/qv4objectproto_p.h | 52 +-- src/qml/jsruntime/qv4scopedvalue_p.h | 26 ++ src/qml/jsruntime/qv4vme_moth.cpp | 4 + 10 files changed, 690 insertions(+), 613 deletions(-) diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 20ba11fd75..759354f4e2 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -44,6 +44,7 @@ #include "qv4argumentsobject_p.h" #include "qv4runtime_p.h" #include "qv4string_p.h" +#include using namespace QV4; @@ -118,42 +119,40 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("reduceRight"), method_reduceRight, 1); } -ReturnedValue ArrayPrototype::method_isArray(CallContext *ctx) +void ArrayPrototype::method_isArray(const BuiltinFunction *, Scope &scope, CallData *callData) { - bool isArray = ctx->argc() && ctx->args()[0].as(); - return Encode(isArray); + bool isArray = callData->argc && callData->args[0].as(); + scope.result = Encode(isArray); } -ReturnedValue ArrayPrototype::method_toString(CallContext *ctx) +void ArrayPrototype::method_toString(const BuiltinFunction *builtin, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject o(scope, ctx->thisObject(), ScopedObject::Convert); - if (ctx->d()->engine->hasException) - return Encode::undefined(); - ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("join"))); + ScopedObject o(scope, callData->thisObject, ScopedObject::Convert); + CHECK_EXCEPTION(); + ScopedString s(scope, scope.engine->newString(QStringLiteral("join"))); ScopedFunctionObject f(scope, o->get(s)); if (!!f) { ScopedCallData d(scope, 0); - d->thisObject = ctx->thisObject(); + d->thisObject = callData->thisObject; f->call(scope, d); - return scope.result.asReturnedValue(); + return; } - return ObjectPrototype::method_toString(ctx); + ObjectPrototype::method_toString(builtin, scope, callData); } -ReturnedValue ArrayPrototype::method_toLocaleString(CallContext *ctx) +void ArrayPrototype::method_toLocaleString(const BuiltinFunction *builtin, Scope &scope, CallData *callData) { - return method_toString(ctx); + return method_toString(builtin, scope, callData); } -ReturnedValue ArrayPrototype::method_concat(CallContext *ctx) +void ArrayPrototype::method_concat(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject result(scope, ctx->d()->engine->newArrayObject()); - - ScopedObject thisObject(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject thisObject(scope, callData->thisObject.toObject(scope.engine)); if (!thisObject) - return Encode::undefined(); + RETURN_UNDEFINED(); + + ScopedArrayObject result(scope, scope.engine->newArrayObject()); + if (thisObject->isArrayObject()) { result->copyArrayData(thisObject); } else { @@ -163,9 +162,9 @@ ReturnedValue ArrayPrototype::method_concat(CallContext *ctx) ScopedArrayObject elt(scope); ScopedObject eltAsObj(scope); ScopedValue entry(scope); - for (int i = 0; i < ctx->argc(); ++i) { - eltAsObj = ctx->args()[i]; - elt = ctx->args()[i]; + for (int i = 0; i < callData->argc; ++i) { + eltAsObj = callData->args[i]; + elt = callData->args[i]; if (elt) { uint n = elt->getLength(); uint newLen = ArrayData::append(result, elt, n); @@ -177,95 +176,90 @@ ReturnedValue ArrayPrototype::method_concat(CallContext *ctx) result->putIndexed(startIndex + i, entry); } } else { - result->arraySet(result->getLength(), ctx->args()[i]); + result->arraySet(result->getLength(), callData->args[i]); } } - return result.asReturnedValue(); + scope.result = result; } -ReturnedValue ArrayPrototype::method_find(CallContext *ctx) +void ArrayPrototype::method_find(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); uint len = instance->getLength(); - ScopedFunctionObject callback(scope, ctx->argument(0)); + ScopedFunctionObject callback(scope, callData->argument(0)); if (!callback) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - ScopedCallData callData(scope, 3); - callData->thisObject = ctx->argument(1); - callData->args[2] = instance; + ScopedCallData cData(scope, 3); + cData->thisObject = callData->argument(1); + cData->args[2] = instance; ScopedValue v(scope); for (uint k = 0; k < len; ++k) { v = instance->getIndexed(k); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); - callData->args[0] = v; - callData->args[1] = Primitive::fromDouble(k); - callback->call(scope, callData); + cData->args[0] = v; + cData->args[1] = Primitive::fromDouble(k); + callback->call(scope, cData); - if (scope.hasException()) - return Encode::undefined(); - else if (scope.result.toBoolean()) - return v->asReturnedValue(); + CHECK_EXCEPTION(); + if (scope.result.toBoolean()) + RETURN_RESULT(v); } - return Encode::undefined(); + RETURN_UNDEFINED(); } -ReturnedValue ArrayPrototype::method_findIndex(CallContext *ctx) +void ArrayPrototype::method_findIndex(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); uint len = instance->getLength(); - ScopedFunctionObject callback(scope, ctx->argument(0)); + ScopedFunctionObject callback(scope, callData->argument(0)); if (!callback) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - ScopedCallData callData(scope, 3); - callData->thisObject = ctx->argument(1); - callData->args[2] = instance; + ScopedCallData cData(scope, 3); + cData->thisObject = callData->argument(1); + cData->args[2] = instance; ScopedValue v(scope); for (uint k = 0; k < len; ++k) { v = instance->getIndexed(k); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); - callData->args[0] = v; - callData->args[1] = Primitive::fromDouble(k); - callback->call(scope, callData); + cData->args[0] = v; + cData->args[1] = Primitive::fromDouble(k); + callback->call(scope, cData); - if (scope.hasException()) - return Encode::undefined(); - else if (scope.result.toBoolean()) - return Encode(k); + CHECK_EXCEPTION(); + if (scope.result.toBoolean()) + RETURN_RESULT(Encode(k)); } - return Encode(-1); + RETURN_RESULT(Encode(-1)); } -ReturnedValue ArrayPrototype::method_join(CallContext *ctx) +void ArrayPrototype::method_join(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedValue arg(scope, ctx->argument(0)); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedValue arg(scope, callData->argument(0)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); - if (!instance) - return ctx->d()->engine->newString()->asReturnedValue(); + if (!instance) { + scope.result = scope.engine->newString(); + return; + } QString r4; if (arg->isUndefined()) @@ -273,11 +267,13 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) else r4 = arg->toQString(); - ScopedValue length(scope, instance->get(ctx->d()->engine->id_length())); + ScopedValue length(scope, instance->get(scope.engine->id_length())); const quint32 r2 = length->isUndefined() ? 0 : length->toUInt32(); - if (!r2) - return ctx->d()->engine->newString()->asReturnedValue(); + if (!r2) { + scope.result = scope.engine->newString(); + return; + } QString R; @@ -289,8 +285,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) R += r4; e = a->getIndexed(i); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); if (!e->isNullOrUndefined()) R += e->toQString(); } @@ -298,7 +293,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) // // crazy! // - ScopedString name(scope, ctx->d()->engine->newString(QStringLiteral("0"))); + ScopedString name(scope, scope.engine->newString(QStringLiteral("0"))); ScopedValue r6(scope, instance->get(name)); if (!r6->isNullOrUndefined()) R = r6->toQString(); @@ -309,99 +304,98 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) name = Primitive::fromDouble(k).toString(scope.engine); r12 = instance->get(name); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); if (!r12->isNullOrUndefined()) R += r12->toQString(); } } - return ctx->d()->engine->newString(R)->asReturnedValue(); + scope.result = scope.engine->newString(R); } -ReturnedValue ArrayPrototype::method_pop(CallContext *ctx) +void ArrayPrototype::method_pop(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); + uint len = instance->getLength(); if (!len) { if (!instance->isArrayObject()) - instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0))); - return Encode::undefined(); + instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0))); + RETURN_UNDEFINED(); } ScopedValue result(scope, instance->getIndexed(len - 1)); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); instance->deleteIndexedProperty(len - 1); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); + if (instance->isArrayObject()) instance->setArrayLength(len - 1); else - instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1))); - return result->asReturnedValue(); + instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1))); + scope.result = result; } -ReturnedValue ArrayPrototype::method_push(CallContext *ctx) +void ArrayPrototype::method_push(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); instance->arrayCreate(); Q_ASSERT(instance->arrayData()); uint len = instance->getLength(); - if (len + ctx->argc() < len) { + if (len + callData->argc < len) { // ughh... double l = len; ScopedString s(scope); - for (int i = 0; i < ctx->argc(); ++i) { + for (int i = 0; i < callData->argc; ++i) { s = Primitive::fromDouble(l + i).toString(scope.engine); - instance->put(s, ctx->args()[i]); + instance->put(s, callData->args[i]); } - double newLen = l + ctx->argc(); + double newLen = l + callData->argc; if (!instance->isArrayObject()) - instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen))); + instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen))); else { - ScopedString str(scope, ctx->d()->engine->newString(QStringLiteral("Array.prototype.push: Overflow"))); - return ctx->engine()->throwRangeError(str); + ScopedString str(scope, scope.engine->newString(QStringLiteral("Array.prototype.push: Overflow"))); + scope.result = scope.engine->throwRangeError(str); + return; } - return Encode(newLen); + scope.result = Encode(newLen); + return; } - if (!ctx->argc()) + if (!callData->argc) ; else if (!instance->protoHasArray() && instance->arrayData()->length() <= len && instance->arrayData()->type == Heap::ArrayData::Simple) { - instance->arrayData()->vtable()->putArray(instance, len, ctx->args(), ctx->argc()); + instance->arrayData()->vtable()->putArray(instance, len, callData->args, callData->argc); len = instance->arrayData()->length(); } else { - for (int i = 0; i < ctx->argc(); ++i) - instance->putIndexed(len + i, ctx->args()[i]); - len += ctx->argc(); + for (int i = 0; i < callData->argc; ++i) + instance->putIndexed(len + i, callData->args[i]); + len += callData->argc; } if (instance->isArrayObject()) instance->setArrayLengthUnchecked(len); else - instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len))); + instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len))); - return Encode(len); + scope.result = Encode(len); } -ReturnedValue ArrayPrototype::method_reverse(CallContext *ctx) +void ArrayPrototype::method_reverse(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); + uint length = instance->getLength(); int lo = 0, hi = length - 1; @@ -412,28 +406,25 @@ ReturnedValue ArrayPrototype::method_reverse(CallContext *ctx) bool loExists, hiExists; lval = instance->getIndexed(lo, &loExists); hval = instance->getIndexed(hi, &hiExists); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); if (hiExists) instance->putIndexed(lo, hval); else instance->deleteIndexedProperty(lo); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); if (loExists) instance->putIndexed(hi, lval); else instance->deleteIndexedProperty(hi); } - return instance.asReturnedValue(); + scope.result = instance; } -ReturnedValue ArrayPrototype::method_shift(CallContext *ctx) +void ArrayPrototype::method_shift(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); instance->arrayCreate(); Q_ASSERT(instance->arrayData()); @@ -442,54 +433,46 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx) if (!len) { if (!instance->isArrayObject()) - instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0))); - return Encode::undefined(); + instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromInt32(0))); + RETURN_UNDEFINED(); } - ScopedValue result(scope); - if (!instance->protoHasArray() && !instance->arrayData()->attrs && instance->arrayData()->length() <= len && instance->arrayData()->type != Heap::ArrayData::Custom) { - result = instance->arrayData()->vtable()->pop_front(instance); + scope.result = instance->arrayData()->vtable()->pop_front(instance); } else { - result = instance->getIndexed(0); - if (scope.hasException()) - return Encode::undefined(); + scope.result = instance->getIndexed(0); + CHECK_EXCEPTION(); ScopedValue v(scope); // do it the slow way for (uint k = 1; k < len; ++k) { bool exists; v = instance->getIndexed(k, &exists); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); if (exists) instance->putIndexed(k - 1, v); else instance->deleteIndexedProperty(k - 1); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); } instance->deleteIndexedProperty(len - 1); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); } if (instance->isArrayObject()) instance->setArrayLengthUnchecked(len - 1); else - instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1))); - return result->asReturnedValue(); + instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - 1))); } -ReturnedValue ArrayPrototype::method_slice(CallContext *ctx) +void ArrayPrototype::method_slice(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject o(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject o(scope, callData->thisObject.toObject(scope.engine)); if (!o) - return Encode::undefined(); + RETURN_UNDEFINED(); - ScopedArrayObject result(scope, ctx->d()->engine->newArrayObject()); + ScopedArrayObject result(scope, scope.engine->newArrayObject()); uint len = o->getLength(); - double s = ScopedValue(scope, ctx->argument(0))->toInteger(); + double s = ScopedValue(scope, callData->argument(0))->toInteger(); uint start; if (s < 0) start = (uint)qMax(len + s, 0.); @@ -498,8 +481,8 @@ ReturnedValue ArrayPrototype::method_slice(CallContext *ctx) else start = (uint) s; uint end = len; - if (ctx->argc() > 1 && !ctx->args()[1].isUndefined()) { - double e = ctx->args()[1].toInteger(); + if (callData->argc > 1 && !callData->args[1].isUndefined()) { + double e = callData->args[1].toInteger(); if (e < 0) end = (uint)qMax(len + e, 0.); else if (e > len) @@ -513,115 +496,107 @@ ReturnedValue ArrayPrototype::method_slice(CallContext *ctx) for (uint i = start; i < end; ++i) { bool exists; v = o->getIndexed(i, &exists); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); if (exists) result->arraySet(n, v); ++n; } - return result.asReturnedValue(); + scope.result = result; } -ReturnedValue ArrayPrototype::method_sort(CallContext *ctx) +void ArrayPrototype::method_sort(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); uint len = instance->getLength(); - ScopedValue comparefn(scope, ctx->argument(0)); + ScopedValue comparefn(scope, callData->argument(0)); ArrayData::sort(scope.engine, instance, comparefn, len); - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject; } -ReturnedValue ArrayPrototype::method_splice(CallContext *ctx) +void ArrayPrototype::method_splice(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); + uint len = instance->getLength(); - ScopedArrayObject newArray(scope, ctx->d()->engine->newArrayObject()); + ScopedArrayObject newArray(scope, scope.engine->newArrayObject()); - double rs = ScopedValue(scope, ctx->argument(0))->toInteger(); + double rs = ScopedValue(scope, callData->argument(0))->toInteger(); uint start; if (rs < 0) start = (uint) qMax(0., len + rs); else start = (uint) qMin(rs, (double)len); - uint deleteCount = (uint)qMin(qMax(ScopedValue(scope, ctx->argument(1))->toInteger(), 0.), (double)(len - start)); + uint deleteCount = (uint)qMin(qMax(ScopedValue(scope, callData->argument(1))->toInteger(), 0.), (double)(len - start)); newArray->arrayReserve(deleteCount); ScopedValue v(scope); for (uint i = 0; i < deleteCount; ++i) { bool exists; v = instance->getIndexed(start + i, &exists); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); if (exists) newArray->arrayPut(i, v); } newArray->setArrayLengthUnchecked(deleteCount); - uint itemCount = ctx->argc() < 2 ? 0 : ctx->argc() - 2; + uint itemCount = callData->argc < 2 ? 0 : callData->argc - 2; if (itemCount < deleteCount) { for (uint k = start; k < len - deleteCount; ++k) { bool exists; v = instance->getIndexed(k + deleteCount, &exists); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); if (exists) instance->putIndexed(k + itemCount, v); else instance->deleteIndexedProperty(k + itemCount); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); } for (uint k = len; k > len - deleteCount + itemCount; --k) { instance->deleteIndexedProperty(k - 1); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); } } else if (itemCount > deleteCount) { uint k = len - deleteCount; while (k > start) { bool exists; v = instance->getIndexed(k + deleteCount - 1, &exists); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); if (exists) instance->putIndexed(k + itemCount - 1, v); else instance->deleteIndexedProperty(k + itemCount - 1); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); --k; } } for (uint i = 0; i < itemCount; ++i) { - instance->putIndexed(start + i, ctx->args()[i + 2]); - if (scope.hasException()) - return Encode::undefined(); + instance->putIndexed(start + i, callData->args[i + 2]); + CHECK_EXCEPTION(); } - ctx->d()->strictMode = true; - instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount))); + bool wasStrict = scope.engine->current->strictMode; + scope.engine->current->strictMode = true; + instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount))); - return newArray.asReturnedValue(); + scope.result = newArray; + scope.engine->current->strictMode = wasStrict; } -ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx) +void ArrayPrototype::method_unshift(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); instance->arrayCreate(); Q_ASSERT(instance->arrayData()); @@ -630,50 +605,52 @@ ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx) if (!instance->protoHasArray() && !instance->arrayData()->attrs && instance->arrayData()->length() <= len && instance->arrayData()->type != Heap::ArrayData::Custom) { - instance->arrayData()->vtable()->push_front(instance, ctx->args(), ctx->argc()); + instance->arrayData()->vtable()->push_front(instance, callData->args, callData->argc); } else { ScopedValue v(scope); for (uint k = len; k > 0; --k) { bool exists; v = instance->getIndexed(k - 1, &exists); if (exists) - instance->putIndexed(k + ctx->argc() - 1, v); + instance->putIndexed(k + callData->argc - 1, v); else - instance->deleteIndexedProperty(k + ctx->argc() - 1); + instance->deleteIndexedProperty(k + callData->argc - 1); } - for (int i = 0; i < ctx->argc(); ++i) - instance->putIndexed(i, ctx->args()[i]); + for (int i = 0; i < callData->argc; ++i) + instance->putIndexed(i, callData->args[i]); } - uint newLen = len + ctx->argc(); + uint newLen = len + callData->argc; if (instance->isArrayObject()) instance->setArrayLengthUnchecked(newLen); else - instance->put(ctx->d()->engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen))); + instance->put(scope.engine->id_length(), ScopedValue(scope, Primitive::fromDouble(newLen))); - return Encode(newLen); + scope.result = Encode(newLen); } -ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx) +void ArrayPrototype::method_indexOf(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); + uint len = instance->getLength(); - if (!len) - return Encode(-1); + if (!len) { + scope.result = Encode(-1); + return; + } - ScopedValue searchValue(scope, ctx->argument(0)); + ScopedValue searchValue(scope, callData->argument(0)); uint fromIndex = 0; - if (ctx->argc() >= 2) { - double f = ctx->args()[1].toInteger(); - if (scope.hasException()) - return Encode::undefined(); - if (f >= len) - return Encode(-1); + if (callData->argc >= 2) { + double f = callData->args[1].toInteger(); + CHECK_EXCEPTION(); + if (f >= len) { + scope.result = Encode(-1); + return; + } if (f < 0) f = qMax(len + f, 0.); fromIndex = (uint) f; @@ -684,10 +661,13 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx) for (uint k = fromIndex; k < len; ++k) { bool exists; v = instance->getIndexed(k, &exists); - if (exists && RuntimeHelpers::strictEqual(v, searchValue)) - return Encode(k); + if (exists && RuntimeHelpers::strictEqual(v, searchValue)) { + scope.result = Encode(k); + return; + } } - return Encode(-1); + scope.result = Encode(-1); + return; } ScopedValue value(scope); @@ -698,13 +678,15 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx) for (uint i = fromIndex; i < len; ++i) { bool exists; value = instance->getIndexed(i, &exists); - if (scope.hasException()) - return Encode::undefined(); - if (exists && RuntimeHelpers::strictEqual(value, searchValue)) - return Encode(i); + CHECK_EXCEPTION(); + if (exists && RuntimeHelpers::strictEqual(value, searchValue)) { + scope.result = Encode(i); + return; + } } } else if (!instance->arrayData()) { - return Encode(-1); + scope.result = Encode(-1); + return; } else { Q_ASSERT(instance->arrayType() == Heap::ArrayData::Simple || instance->arrayType() == Heap::ArrayData::Complex); Heap::SimpleArrayData *sa = instance->d()->arrayData.cast(); @@ -713,45 +695,48 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx) uint idx = fromIndex; while (idx < len) { value = sa->data(idx); - if (scope.hasException()) - return Encode::undefined(); - if (RuntimeHelpers::strictEqual(value, searchValue)) - return Encode(idx); + CHECK_EXCEPTION(); + if (RuntimeHelpers::strictEqual(value, searchValue)) { + scope.result = Encode(idx); + return; + } ++idx; } } - return Encode(-1); + scope.result = Encode(-1); } -ReturnedValue ArrayPrototype::method_lastIndexOf(CallContext *ctx) +void ArrayPrototype::method_lastIndexOf(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); + uint len = instance->getLength(); - if (!len) - return Encode(-1); + if (!len) { + scope.result = Encode(-1); + return; + } ScopedValue searchValue(scope); uint fromIndex = len; - if (ctx->argc() >= 1) - searchValue = ctx->argument(0); + if (callData->argc >= 1) + searchValue = callData->argument(0); else searchValue = Primitive::undefinedValue(); - if (ctx->argc() >= 2) { - double f = ctx->args()[1].toInteger(); - if (scope.hasException()) - return Encode::undefined(); + if (callData->argc >= 2) { + double f = callData->args[1].toInteger(); + CHECK_EXCEPTION(); if (f > 0) f = qMin(f, (double)(len - 1)); else if (f < 0) { f = len + f; - if (f < 0) - return Encode(-1); + if (f < 0) { + scope.result = Encode(-1); + return; + } } fromIndex = (uint) f + 1; } @@ -761,30 +746,30 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(CallContext *ctx) --k; bool exists; v = instance->getIndexed(k, &exists); - if (scope.hasException()) - return Encode::undefined(); - if (exists && RuntimeHelpers::strictEqual(v, searchValue)) - return Encode(k); + CHECK_EXCEPTION(); + if (exists && RuntimeHelpers::strictEqual(v, searchValue)) { + scope.result = Encode(k); + return; + } } - return Encode(-1); + scope.result = Encode(-1); } -ReturnedValue ArrayPrototype::method_every(CallContext *ctx) +void ArrayPrototype::method_every(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); uint len = instance->getLength(); - ScopedFunctionObject callback(scope, ctx->argument(0)); + ScopedFunctionObject callback(scope, callData->argument(0)); if (!callback) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - ScopedCallData callData(scope, 3); - callData->args[2] = instance; - callData->thisObject = ctx->argument(1); + ScopedCallData cData(scope, 3); + cData->args[2] = instance; + cData->thisObject = callData->argument(1); ScopedValue v(scope); bool ok = true; @@ -794,30 +779,29 @@ ReturnedValue ArrayPrototype::method_every(CallContext *ctx) if (!exists) continue; - callData->args[0] = v; - callData->args[1] = Primitive::fromDouble(k); - callback->call(scope, callData); + cData->args[0] = v; + cData->args[1] = Primitive::fromDouble(k); + callback->call(scope, cData); ok = scope.result.toBoolean(); } - return Encode(ok); + scope.result = Encode(ok); } -ReturnedValue ArrayPrototype::method_some(CallContext *ctx) +void ArrayPrototype::method_some(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); uint len = instance->getLength(); - ScopedFunctionObject callback(scope, ctx->argument(0)); + ScopedFunctionObject callback(scope, callData->argument(0)); if (!callback) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - ScopedCallData callData(scope, 3); - callData->thisObject = ctx->argument(1); - callData->args[2] = instance; + ScopedCallData cData(scope, 3); + cData->thisObject = callData->argument(1); + cData->args[2] = instance; ScopedValue v(scope); for (uint k = 0; k < len; ++k) { @@ -826,31 +810,32 @@ ReturnedValue ArrayPrototype::method_some(CallContext *ctx) if (!exists) continue; - callData->args[0] = v; - callData->args[1] = Primitive::fromDouble(k); - callback->call(scope, callData); - if (scope.result.toBoolean()) - return Encode(true); + cData->args[0] = v; + cData->args[1] = Primitive::fromDouble(k); + callback->call(scope, cData); + if (scope.result.toBoolean()) { + scope.result = Encode(true); + return; + } } - return Encode(false); + scope.result = Encode(false); } -ReturnedValue ArrayPrototype::method_forEach(CallContext *ctx) +void ArrayPrototype::method_forEach(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); uint len = instance->getLength(); - ScopedFunctionObject callback(scope, ctx->argument(0)); + ScopedFunctionObject callback(scope, callData->argument(0)); if (!callback) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - ScopedCallData callData(scope, 3); - callData->thisObject = ctx->argument(1); - callData->args[2] = instance; + ScopedCallData cData(scope, 3); + cData->thisObject = callData->argument(1); + cData->args[2] = instance; ScopedValue v(scope); for (uint k = 0; k < len; ++k) { @@ -859,33 +844,32 @@ ReturnedValue ArrayPrototype::method_forEach(CallContext *ctx) if (!exists) continue; - callData->args[0] = v; - callData->args[1] = Primitive::fromDouble(k); - callback->call(scope, callData); + cData->args[0] = v; + cData->args[1] = Primitive::fromDouble(k); + callback->call(scope, cData); } - return Encode::undefined(); + RETURN_UNDEFINED(); } -ReturnedValue ArrayPrototype::method_map(CallContext *ctx) +void ArrayPrototype::method_map(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); uint len = instance->getLength(); - ScopedFunctionObject callback(scope, ctx->argument(0)); + ScopedFunctionObject callback(scope, callData->argument(0)); if (!callback) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - ScopedArrayObject a(scope, ctx->d()->engine->newArrayObject()); + ScopedArrayObject a(scope, scope.engine->newArrayObject()); a->arrayReserve(len); a->setArrayLengthUnchecked(len); - ScopedCallData callData(scope, 3); - callData->thisObject = ctx->argument(1); - callData->args[2] = instance; + ScopedCallData cData(scope, 3); + cData->thisObject = callData->argument(1); + cData->args[2] = instance; ScopedValue v(scope); for (uint k = 0; k < len; ++k) { @@ -894,33 +878,32 @@ ReturnedValue ArrayPrototype::method_map(CallContext *ctx) if (!exists) continue; - callData->args[0] = v; - callData->args[1] = Primitive::fromDouble(k); - callback->call(scope, callData); + cData->args[0] = v; + cData->args[1] = Primitive::fromDouble(k); + callback->call(scope, cData); a->arraySet(k, scope.result); } - return a.asReturnedValue(); + scope.result = a.asReturnedValue(); } -ReturnedValue ArrayPrototype::method_filter(CallContext *ctx) +void ArrayPrototype::method_filter(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); uint len = instance->getLength(); - ScopedFunctionObject callback(scope, ctx->argument(0)); + ScopedFunctionObject callback(scope, callData->argument(0)); if (!callback) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - ScopedArrayObject a(scope, ctx->d()->engine->newArrayObject()); + ScopedArrayObject a(scope, scope.engine->newArrayObject()); a->arrayReserve(len); - ScopedCallData callData(scope, 3); - callData->thisObject = ctx->argument(1); - callData->args[2] = instance; + ScopedCallData cData(scope, 3); + cData->thisObject = callData->argument(1); + cData->args[2] = instance; ScopedValue v(scope); @@ -931,35 +914,34 @@ ReturnedValue ArrayPrototype::method_filter(CallContext *ctx) if (!exists) continue; - callData->args[0] = v; - callData->args[1] = Primitive::fromDouble(k); - callback->call(scope, callData); + cData->args[0] = v; + cData->args[1] = Primitive::fromDouble(k); + callback->call(scope, cData); if (scope.result.toBoolean()) { a->arraySet(to, v); ++to; } } - return a.asReturnedValue(); + scope.result = a.asReturnedValue(); } -ReturnedValue ArrayPrototype::method_reduce(CallContext *ctx) +void ArrayPrototype::method_reduce(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); uint len = instance->getLength(); - ScopedFunctionObject callback(scope, ctx->argument(0)); + ScopedFunctionObject callback(scope, callData->argument(0)); if (!callback) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); uint k = 0; ScopedValue v(scope); - if (ctx->argc() > 1) { - scope.result = ctx->argument(1); + if (callData->argc > 1) { + scope.result = callData->argument(1); } else { bool kPresent = false; while (k < len && !kPresent) { @@ -969,51 +951,50 @@ ReturnedValue ArrayPrototype::method_reduce(CallContext *ctx) ++k; } if (!kPresent) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); } - ScopedCallData callData(scope, 4); - callData->thisObject = Primitive::undefinedValue(); - callData->args[0] = scope.result; - callData->args[3] = instance; + ScopedCallData cData(scope, 4); + cData->thisObject = Primitive::undefinedValue(); + cData->args[0] = scope.result; + cData->args[3] = instance; while (k < len) { bool kPresent; v = instance->getIndexed(k, &kPresent); if (kPresent) { - callData->args[0] = scope.result; - callData->args[1] = v; - callData->args[2] = Primitive::fromDouble(k); - callback->call(scope, callData); + cData->args[0] = scope.result; + cData->args[1] = v; + cData->args[2] = Primitive::fromDouble(k); + callback->call(scope, cData); } ++k; } - return scope.result.asReturnedValue(); } -ReturnedValue ArrayPrototype::method_reduceRight(CallContext *ctx) +void ArrayPrototype::method_reduceRight(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject instance(scope, callData->thisObject.toObject(scope.engine)); if (!instance) - return Encode::undefined(); + RETURN_UNDEFINED(); uint len = instance->getLength(); - ScopedFunctionObject callback(scope, ctx->argument(0)); + ScopedFunctionObject callback(scope, callData->argument(0)); if (!callback) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); if (len == 0) { - if (ctx->argc() == 1) - return ctx->engine()->throwTypeError(); - return ctx->argument(1); + if (callData->argc == 1) + THROW_TYPE_ERROR(); + scope.result = callData->argument(1); + return; } uint k = len; ScopedValue v(scope); - if (ctx->argc() > 1) { - scope.result = ctx->argument(1); + if (callData->argc > 1) { + scope.result = callData->argument(1); } else { bool kPresent = false; while (k > 0 && !kPresent) { @@ -1023,24 +1004,24 @@ ReturnedValue ArrayPrototype::method_reduceRight(CallContext *ctx) --k; } if (!kPresent) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); } - ScopedCallData callData(scope, 4); - callData->thisObject = Primitive::undefinedValue(); - callData->args[3] = instance; + ScopedCallData cData(scope, 4); + cData->thisObject = Primitive::undefinedValue(); + cData->args[3] = instance; while (k > 0) { bool kPresent; v = instance->getIndexed(k - 1, &kPresent); if (kPresent) { - callData->args[0] = scope.result; - callData->args[1] = v; - callData->args[2] = Primitive::fromDouble(k - 1); - callback->call(scope, callData); + cData->args[0] = scope.result; + cData->args[1] = v; + cData->args[2] = Primitive::fromDouble(k - 1); + callback->call(scope, cData); } --k; } - return scope.result.asReturnedValue(); + scope.result = scope.result.asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h index f00c0c0249..689752433b 100644 --- a/src/qml/jsruntime/qv4arrayobject_p.h +++ b/src/qml/jsruntime/qv4arrayobject_p.h @@ -78,30 +78,30 @@ struct ArrayPrototype: ArrayObject { void init(ExecutionEngine *engine, Object *ctor); - static ReturnedValue method_isArray(CallContext *ctx); - static ReturnedValue method_toString(CallContext *ctx); - static ReturnedValue method_toLocaleString(CallContext *ctx); - static ReturnedValue method_concat(CallContext *ctx); - static ReturnedValue method_find(CallContext *ctx); - static ReturnedValue method_findIndex(CallContext *ctx); - static ReturnedValue method_join(CallContext *ctx); - static ReturnedValue method_pop(CallContext *ctx); - static ReturnedValue method_push(CallContext *ctx); - static ReturnedValue method_reverse(CallContext *ctx); - static ReturnedValue method_shift(CallContext *ctx); - static ReturnedValue method_slice(CallContext *ctx); - static ReturnedValue method_sort(CallContext *ctx); - static ReturnedValue method_splice(CallContext *ctx); - static ReturnedValue method_unshift(CallContext *ctx); - static ReturnedValue method_indexOf(CallContext *ctx); - static ReturnedValue method_lastIndexOf(CallContext *ctx); - static ReturnedValue method_every(CallContext *ctx); - static ReturnedValue method_some(CallContext *ctx); - static ReturnedValue method_forEach(CallContext *ctx); - static ReturnedValue method_map(CallContext *ctx); - static ReturnedValue method_filter(CallContext *ctx); - static ReturnedValue method_reduce(CallContext *ctx); - static ReturnedValue method_reduceRight(CallContext *ctx); + static void method_isArray(const BuiltinFunction *, Scope &, CallData *callData); + static void method_toString(const BuiltinFunction *, Scope &, CallData *callData); + static void method_toLocaleString(const BuiltinFunction *builtin, Scope &, CallData *callData); + static void method_concat(const BuiltinFunction *, Scope &, CallData *callData); + static void method_find(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_findIndex(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_join(const BuiltinFunction *, Scope &, CallData *callData); + static void method_pop(const BuiltinFunction *, Scope &, CallData *callData); + static void method_push(const BuiltinFunction *, Scope &, CallData *callData); + static void method_reverse(const BuiltinFunction *, Scope &, CallData *callData); + static void method_shift(const BuiltinFunction *, Scope &, CallData *callData); + static void method_slice(const BuiltinFunction *, Scope &, CallData *callData); + static void method_sort(const BuiltinFunction *, Scope &, CallData *callData); + static void method_splice(const BuiltinFunction *, Scope &, CallData *callData); + static void method_unshift(const BuiltinFunction *, Scope &, CallData *callData); + static void method_indexOf(const BuiltinFunction *, Scope &, CallData *callData); + static void method_lastIndexOf(const BuiltinFunction *, Scope &, CallData *callData); + static void method_every(const BuiltinFunction *, Scope &, CallData *callData); + static void method_some(const BuiltinFunction *, Scope &, CallData *callData); + static void method_forEach(const BuiltinFunction *, Scope &, CallData *callData); + static void method_map(const BuiltinFunction *, Scope &, CallData *callData); + static void method_filter(const BuiltinFunction *, Scope &, CallData *callData); + static void method_reduce(const BuiltinFunction *, Scope &, CallData *callData); + static void method_reduceRight(const BuiltinFunction *, Scope &, CallData *callData); }; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 3bbccdba2f..1458c77d88 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -459,22 +459,22 @@ Heap::Object *ScriptFunction::protoForConstructor() const -DEFINE_OBJECT_VTABLE(BuiltinFunction); +DEFINE_OBJECT_VTABLE(OldBuiltinFunction); -void Heap::BuiltinFunction::init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *)) +void Heap::OldBuiltinFunction::init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *)) { Heap::FunctionObject::init(scope, name); this->code = code; } -void BuiltinFunction::construct(const Managed *f, Scope &scope, CallData *) +void OldBuiltinFunction::construct(const Managed *f, Scope &scope, CallData *) { - scope.result = static_cast(f)->internalClass()->engine->throwTypeError(); + scope.result = static_cast(f)->internalClass()->engine->throwTypeError(); } -void BuiltinFunction::call(const Managed *that, Scope &scope, CallData *callData) +void OldBuiltinFunction::call(const Managed *that, Scope &scope, CallData *callData) { - const BuiltinFunction *f = static_cast(that); + const OldBuiltinFunction *f = static_cast(that); ExecutionEngine *v4 = scope.engine; if (v4->hasException) { scope.result = Encode::undefined(); @@ -494,6 +494,31 @@ void BuiltinFunction::call(const Managed *that, Scope &scope, CallData *callData v4->memoryManager->freeSimpleCallContext(); } +DEFINE_OBJECT_VTABLE(BuiltinFunction); + +void Heap::BuiltinFunction::init(QV4::ExecutionContext *scope, QV4::String *name, void (*code)(const QV4::BuiltinFunction *, Scope &, CallData *)) +{ + Heap::FunctionObject::init(scope, name); + this->code = code; +} + +void BuiltinFunction::construct(const Managed *f, Scope &scope, CallData *) +{ + scope.result = static_cast(f)->internalClass()->engine->throwTypeError(); +} + +void BuiltinFunction::call(const Managed *that, Scope &scope, CallData *callData) +{ + const BuiltinFunction *f = static_cast(that); + ExecutionEngine *v4 = scope.engine; + if (v4->hasException) { + scope.result = Encode::undefined(); + return; + } + f->d()->code(f, scope, callData); +} + + void IndexedBuiltinFunction::call(const Managed *that, Scope &scope, CallData *callData) { const IndexedBuiltinFunction *f = static_cast(that); diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index a02e89e883..31b05666a7 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -61,6 +61,8 @@ struct QQmlSourceLocation; namespace QV4 { +struct BuiltinFunction; + namespace Heap { struct Q_QML_PRIVATE_EXPORT FunctionObject : Object { @@ -93,11 +95,16 @@ struct FunctionPrototype : FunctionObject { void init(); }; -struct Q_QML_EXPORT BuiltinFunction : FunctionObject { +struct Q_QML_EXPORT OldBuiltinFunction : FunctionObject { void init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *)); ReturnedValue (*code)(QV4::CallContext *); }; +struct Q_QML_EXPORT BuiltinFunction : FunctionObject { + void init(QV4::ExecutionContext *scope, QV4::String *name, void (*code)(const QV4::BuiltinFunction *, Scope &, CallData *)); + void (*code)(const QV4::BuiltinFunction *, Scope &, CallData *); +}; + struct IndexedBuiltinFunction : FunctionObject { inline void init(QV4::ExecutionContext *scope, uint index, ReturnedValue (*code)(QV4::CallContext *ctx, uint index)); ReturnedValue (*code)(QV4::CallContext *, uint index); @@ -183,10 +190,21 @@ struct FunctionPrototype: FunctionObject static ReturnedValue method_bind(CallContext *ctx); }; -struct Q_QML_EXPORT BuiltinFunction: FunctionObject { +struct Q_QML_EXPORT OldBuiltinFunction : FunctionObject { + V4_OBJECT2(OldBuiltinFunction, FunctionObject) + + static void construct(const Managed *, Scope &scope, CallData *); + static void call(const Managed *that, Scope &scope, CallData *callData); +}; + +struct Q_QML_EXPORT BuiltinFunction : FunctionObject { V4_OBJECT2(BuiltinFunction, FunctionObject) - static Heap::BuiltinFunction *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *)) + static Heap::OldBuiltinFunction *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *)) + { + return scope->engine()->memoryManager->allocObject(scope, name, code); + } + static Heap::BuiltinFunction *create(ExecutionContext *scope, String *name, void (*code)(const BuiltinFunction *, Scope &, CallData *)) { return scope->engine()->memoryManager->allocObject(scope, name, code); } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index f217e301ac..cb13069ca0 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -166,6 +166,17 @@ void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(Ca defineDefaultProperty(s, function); } +void Object::defineDefaultProperty(const QString &name, void (*code)(const BuiltinFunction *, Scope &, CallData *), int argumentCount) +{ + ExecutionEngine *e = engine(); + Scope scope(e); + ScopedString s(scope, e->newIdentifier(name)); + ExecutionContext *global = e->rootContext(); + ScopedFunctionObject function(scope, BuiltinFunction::create(global, s, code)); + function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount)); + defineDefaultProperty(s, function); +} + void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(CallContext *), int argumentCount) { ExecutionEngine *e = engine(); @@ -176,6 +187,16 @@ void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(CallConte defineDefaultProperty(name, function); } +void Object::defineDefaultProperty(String *name, void (*code)(const BuiltinFunction *, Scope &, CallData *), int argumentCount) +{ + ExecutionEngine *e = engine(); + Scope scope(e); + ExecutionContext *global = e->rootContext(); + ScopedFunctionObject function(scope, BuiltinFunction::create(global, name, code)); + function->defineReadonlyProperty(e->id_length(), Primitive::fromInt32(argumentCount)); + defineDefaultProperty(name, function); +} + void Object::defineAccessorProperty(const QString &name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *)) { ExecutionEngine *e = engine(); diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 65820911db..cf9d7bbcdf 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -63,6 +63,8 @@ QT_BEGIN_NAMESPACE namespace QV4 { +struct BuiltinFunction; + namespace Heap { struct Object : Base { @@ -236,7 +238,9 @@ struct Q_QML_EXPORT Object: Managed { } void defineDefaultProperty(const QString &name, const Value &value); void defineDefaultProperty(const QString &name, ReturnedValue (*code)(CallContext *), int argumentCount = 0); + void defineDefaultProperty(const QString &name, void (*code)(const BuiltinFunction *, Scope &, CallData *), int argumentCount = 0); void defineDefaultProperty(String *name, ReturnedValue (*code)(CallContext *), int argumentCount = 0); + void defineDefaultProperty(String *name, void (*code)(const BuiltinFunction *, Scope &, CallData *), int argumentCount = 0); void defineAccessorProperty(const QString &name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *)); void defineAccessorProperty(String *name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *)); /* Fixed: Writable: false, Enumerable: false, Configurable: false */ diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index 8191083544..97dbe24339 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -121,100 +121,100 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor) insertMember(v4->id___proto__(), p, Attr_Accessor|Attr_NotEnumerable); } -ReturnedValue ObjectPrototype::method_getPrototypeOf(CallContext *ctx) +void ObjectPrototype::method_getPrototypeOf(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject o(scope, ctx->argument(0)); + ScopedObject o(scope, callData->argument(0)); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); ScopedObject p(scope, o->prototype()); - return !!p ? p->asReturnedValue() : Encode::null(); + scope.result = !!p ? p->asReturnedValue() : Encode::null(); } -ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(CallContext *ctx) +void ObjectPrototype::method_getOwnPropertyDescriptor(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject O(scope, ctx->argument(0)); - if (!O) - return ctx->engine()->throwTypeError(); + ScopedObject O(scope, callData->argument(0)); + if (!O) { + scope.result = scope.engine->throwTypeError(); + return; + } if (ArgumentsObject::isNonStrictArgumentsObject(O)) static_cast(O.getPointer())->fullyCreate(); - ScopedValue v(scope, ctx->argument(1)); + ScopedValue v(scope, callData->argument(1)); ScopedString name(scope, v->toString(scope.engine)); - if (scope.hasException()) - return Encode::undefined(); + CHECK_EXCEPTION(); + PropertyAttributes attrs; ScopedProperty desc(scope); O->getOwnProperty(name, &attrs, desc); - return fromPropertyDescriptor(scope.engine, desc, attrs); + scope.result = fromPropertyDescriptor(scope.engine, desc, attrs); } -ReturnedValue ObjectPrototype::method_getOwnPropertyNames(CallContext *context) +void ObjectPrototype::method_getOwnPropertyNames(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(context); - ScopedObject O(scope, context->argument(0)); - if (!O) - return context->engine()->throwTypeError(); + ScopedObject O(scope, callData->argument(0)); + if (!O) { + scope.result = scope.engine->throwTypeError(); + return; + } - ScopedArrayObject array(scope, getOwnPropertyNames(context->d()->engine, context->args()[0])); - return array.asReturnedValue(); + scope.result = getOwnPropertyNames(scope.engine, callData->args[0]); } -ReturnedValue ObjectPrototype::method_create(CallContext *ctx) +void ObjectPrototype::method_create(const BuiltinFunction *builtin, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedValue O(scope, ctx->argument(0)); - if (!O->isObject() && !O->isNull()) - return ctx->engine()->throwTypeError(); + ScopedValue O(scope, callData->argument(0)); + if (!O->isObject() && !O->isNull()) { + scope.result = scope.engine->throwTypeError(); + return; + } - ScopedObject newObject(scope, ctx->d()->engine->newObject()); + ScopedObject newObject(scope, scope.engine->newObject()); newObject->setPrototype(O->as()); - if (ctx->argc() > 1 && !ctx->args()[1].isUndefined()) { - ctx->d()->callData->args[0] = newObject.asReturnedValue(); - return method_defineProperties(ctx); + if (callData->argc > 1 && !callData->args[1].isUndefined()) { + callData->args[0] = newObject; + method_defineProperties(builtin, scope, callData); + return; } - return newObject.asReturnedValue(); + scope.result = newObject; } -ReturnedValue ObjectPrototype::method_defineProperty(CallContext *ctx) +void ObjectPrototype::method_defineProperty(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject O(scope, ctx->argument(0)); - if (!O) - return ctx->engine()->throwTypeError(); + ScopedObject O(scope, callData->argument(0)); + if (!O) { + scope.result = scope.engine->throwTypeError(); + return; + } - ScopedString name(scope, ctx->argument(1), ScopedString::Convert); - if (scope.engine->hasException) - return Encode::undefined(); + ScopedString name(scope, callData->argument(1), ScopedString::Convert); + CHECK_EXCEPTION(); - ScopedValue attributes(scope, ctx->argument(2)); + ScopedValue attributes(scope, callData->argument(2)); ScopedProperty pd(scope); PropertyAttributes attrs; toPropertyDescriptor(scope.engine, attributes, pd, &attrs); - if (scope.engine->hasException) - return Encode::undefined(); + CHECK_EXCEPTION(); if (!O->__defineOwnProperty__(scope.engine, name, pd, attrs)) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - return O.asReturnedValue(); + scope.result = O; } -ReturnedValue ObjectPrototype::method_defineProperties(CallContext *ctx) +void ObjectPrototype::method_defineProperties(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject O(scope, ctx->argument(0)); + ScopedObject O(scope, callData->argument(0)); if (!O) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); + + ScopedObject o(scope, callData->argument(1), ScopedObject::Convert); + CHECK_EXCEPTION(); - ScopedObject o(scope, ctx->argument(1), ScopedObject::Convert); - if (scope.engine->hasException) - return Encode::undefined(); ScopedValue val(scope); ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly); @@ -230,26 +230,24 @@ ReturnedValue ObjectPrototype::method_defineProperties(CallContext *ctx) PropertyAttributes nattrs; val = o->getValue(pd->value, attrs); toPropertyDescriptor(scope.engine, val, n, &nattrs); - if (scope.engine->hasException) - return Encode::undefined(); + CHECK_EXCEPTION(); bool ok; if (name) ok = O->__defineOwnProperty__(scope.engine, name, n, nattrs); else ok = O->__defineOwnProperty__(scope.engine, index, n, nattrs); if (!ok) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); } - return O.asReturnedValue(); + scope.result = O; } -ReturnedValue ObjectPrototype::method_seal(CallContext *ctx) +void ObjectPrototype::method_seal(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject o(scope, ctx->argument(0)); + ScopedObject o(scope, callData->argument(0)); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); o->setInternalClass(o->internalClass()->sealed()); @@ -261,15 +259,14 @@ ReturnedValue ObjectPrototype::method_seal(CallContext *ctx) } } - return o.asReturnedValue(); + scope.result = o; } -ReturnedValue ObjectPrototype::method_freeze(CallContext *ctx) +void ObjectPrototype::method_freeze(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject o(scope, ctx->argument(0)); + ScopedObject o(scope, callData->argument(0)); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); if (ArgumentsObject::isNonStrictArgumentsObject(o)) static_cast(o.getPointer())->fullyCreate(); @@ -285,96 +282,111 @@ ReturnedValue ObjectPrototype::method_freeze(CallContext *ctx) o->arrayData()->attrs[i].setWritable(false); } } - return o.asReturnedValue(); + scope.result = o; } -ReturnedValue ObjectPrototype::method_preventExtensions(CallContext *ctx) +void ObjectPrototype::method_preventExtensions(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject o(scope, ctx->argument(0)); + ScopedObject o(scope, callData->argument(0)); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); o->setInternalClass(o->internalClass()->nonExtensible()); - return o.asReturnedValue(); + scope.result = o; } -ReturnedValue ObjectPrototype::method_isSealed(CallContext *ctx) +void ObjectPrototype::method_isSealed(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject o(scope, ctx->argument(0)); + ScopedObject o(scope, callData->argument(0)); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - if (o->isExtensible()) - return Encode(false); + if (o->isExtensible()) { + scope.result = Encode(false); + return; + } - if (o->internalClass() != o->internalClass()->sealed()) - return Encode(false); + if (o->internalClass() != o->internalClass()->sealed()) { + scope.result = Encode(false); + return; + } - if (!o->arrayData() || !o->arrayData()->length()) - return Encode(true); + if (!o->arrayData() || !o->arrayData()->length()) { + scope.result = Encode(true); + return; + } Q_ASSERT(o->arrayData() && o->arrayData()->length()); - if (!o->arrayData()->attrs) - return Encode(false); + if (!o->arrayData()->attrs) { + scope.result = Encode(false); + return; + } for (uint i = 0; i < o->arrayData()->alloc; ++i) { if (!o->arrayData()->isEmpty(i)) - if (o->arrayData()->attributes(i).isConfigurable()) - return Encode(false); + if (o->arrayData()->attributes(i).isConfigurable()) { + scope.result = Encode(false); + return; + } } - return Encode(true); + scope.result = Encode(true); } -ReturnedValue ObjectPrototype::method_isFrozen(CallContext *ctx) +void ObjectPrototype::method_isFrozen(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject o(scope, ctx->argument(0)); + ScopedObject o(scope, callData->argument(0)); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - if (o->isExtensible()) - return Encode(false); + if (o->isExtensible()) { + scope.result = Encode(false); + return; + } - if (o->internalClass() != o->internalClass()->frozen()) - return Encode(false); + if (o->internalClass() != o->internalClass()->frozen()) { + scope.result = Encode(false); + return; + } - if (!o->arrayData() || !o->arrayData()->length()) - return Encode(true); + if (!o->arrayData() || !o->arrayData()->length()) { + scope.result = Encode(true); + return; + } Q_ASSERT(o->arrayData() && o->arrayData()->length()); - if (!o->arrayData()->attrs) - return Encode(false); + if (!o->arrayData()->attrs) { + scope.result = Encode(false); + return; + } for (uint i = 0; i < o->arrayData()->alloc; ++i) { if (!o->arrayData()->isEmpty(i)) - if (o->arrayData()->attributes(i).isConfigurable() || o->arrayData()->attributes(i).isWritable()) - return Encode(false); + if (o->arrayData()->attributes(i).isConfigurable() || o->arrayData()->attributes(i).isWritable()) { + scope.result = Encode(false); + return; + } } - return Encode(true); + scope.result = Encode(true); } -ReturnedValue ObjectPrototype::method_isExtensible(CallContext *ctx) +void ObjectPrototype::method_isExtensible(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject o(scope, ctx->argument(0)); + ScopedObject o(scope, callData->argument(0)); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - return Encode((bool)o->isExtensible()); + scope.result = Encode((bool)o->isExtensible()); } -ReturnedValue ObjectPrototype::method_keys(CallContext *ctx) +void ObjectPrototype::method_keys(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject o(scope, ctx->argument(0)); + ScopedObject o(scope, callData->argument(0)); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - ScopedArrayObject a(scope, ctx->d()->engine->newArrayObject()); + ScopedArrayObject a(scope, scope.engine->newArrayObject()); ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly); ScopedValue name(scope); @@ -385,175 +397,159 @@ ReturnedValue ObjectPrototype::method_keys(CallContext *ctx) a->push_back(name); } - return a.asReturnedValue(); + scope.result = a; } -ReturnedValue ObjectPrototype::method_toString(CallContext *ctx) +void ObjectPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - if (ctx->thisObject().isUndefined()) { - return ctx->d()->engine->newString(QStringLiteral("[object Undefined]"))->asReturnedValue(); - } else if (ctx->thisObject().isNull()) { - return ctx->d()->engine->newString(QStringLiteral("[object Null]"))->asReturnedValue(); + if (callData->thisObject.isUndefined()) { + scope.result = scope.engine->newString(QStringLiteral("[object Undefined]")); + } else if (callData->thisObject.isNull()) { + scope.result = scope.engine->newString(QStringLiteral("[object Null]")); } else { - ScopedObject obj(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject obj(scope, callData->thisObject.toObject(scope.engine)); QString className = obj->className(); - return ctx->d()->engine->newString(QStringLiteral("[object %1]").arg(className))->asReturnedValue(); + scope.result = scope.engine->newString(QStringLiteral("[object %1]").arg(className)); } } -ReturnedValue ObjectPrototype::method_toLocaleString(CallContext *ctx) +void ObjectPrototype::method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject o(scope, ctx->thisObject().toObject(scope.engine)); + ScopedObject o(scope, callData->thisObject.toObject(scope.engine)); if (!o) - return Encode::undefined(); - ScopedFunctionObject f(scope, o->get(ctx->d()->engine->id_toString())); + RETURN_UNDEFINED(); + + ScopedFunctionObject f(scope, o->get(scope.engine->id_toString())); if (!f) - return ctx->engine()->throwTypeError(); - ScopedCallData callData(scope); - callData->thisObject = o; + THROW_TYPE_ERROR(); + ScopedCallData cData(scope); + cData->thisObject = o; f->call(scope, callData); - return scope.result.asReturnedValue(); } -ReturnedValue ObjectPrototype::method_valueOf(CallContext *ctx) +void ObjectPrototype::method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedValue v(scope, ctx->thisObject().toObject(scope.engine)); - if (ctx->d()->engine->hasException) - return Encode::undefined(); - return v->asReturnedValue(); + scope.result = callData->thisObject.toObject(scope.engine); } -ReturnedValue ObjectPrototype::method_hasOwnProperty(CallContext *ctx) +void ObjectPrototype::method_hasOwnProperty(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedString P(scope, ctx->argument(0), ScopedString::Convert); - if (scope.engine->hasException) - return Encode::undefined(); - ScopedObject O(scope, ctx->thisObject(), ScopedObject::Convert); - if (scope.engine->hasException) - return Encode::undefined(); + ScopedString P(scope, callData->argument(0), ScopedString::Convert); + CHECK_EXCEPTION(); + ScopedObject O(scope, callData->thisObject, ScopedObject::Convert); + CHECK_EXCEPTION(); bool r = O->hasOwnProperty(P); if (!r) r = !O->query(P).isEmpty(); - return Encode(r); + scope.result = Encode(r); } -ReturnedValue ObjectPrototype::method_isPrototypeOf(CallContext *ctx) +void ObjectPrototype::method_isPrototypeOf(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject V(scope, ctx->argument(0)); - if (!V) - return Encode(false); + ScopedObject V(scope, callData->argument(0)); + if (!V) { + scope.result = Encode(false); + return; + } - ScopedObject O(scope, ctx->thisObject(), ScopedObject::Convert); - if (scope.engine->hasException) - return Encode::undefined(); + ScopedObject O(scope, callData->thisObject, ScopedObject::Convert); + CHECK_EXCEPTION(); ScopedObject proto(scope, V->prototype()); while (proto) { - if (O->d() == proto->d()) - return Encode(true); + if (O->d() == proto->d()) { + scope.result = Encode(true); + return; + } proto = proto->prototype(); } - return Encode(false); + scope.result = Encode(false); } -ReturnedValue ObjectPrototype::method_propertyIsEnumerable(CallContext *ctx) +void ObjectPrototype::method_propertyIsEnumerable(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedString p(scope, ctx->argument(0), ScopedString::Convert); - if (scope.engine->hasException) - return Encode::undefined(); + ScopedString p(scope, callData->argument(0), ScopedString::Convert); + CHECK_EXCEPTION(); - ScopedObject o(scope, ctx->thisObject(), ScopedObject::Convert); - if (scope.engine->hasException) - return Encode::undefined(); + ScopedObject o(scope, callData->thisObject, ScopedObject::Convert); + CHECK_EXCEPTION(); PropertyAttributes attrs; o->getOwnProperty(p, &attrs); - return Encode(attrs.isEnumerable()); + scope.result = Encode(attrs.isEnumerable()); } -ReturnedValue ObjectPrototype::method_defineGetter(CallContext *ctx) +void ObjectPrototype::method_defineGetter(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() < 2) - return ctx->engine()->throwTypeError(); + if (callData->argc < 2) + THROW_TYPE_ERROR(); - Scope scope(ctx); - ScopedFunctionObject f(scope, ctx->argument(1)); + ScopedFunctionObject f(scope, callData->argument(1)); if (!f) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - ScopedString prop(scope, ctx->argument(0), ScopedString::Convert); - if (scope.engine->hasException) - return Encode::undefined(); + ScopedString prop(scope, callData->argument(0), ScopedString::Convert); + CHECK_EXCEPTION(); - ScopedObject o(scope, ctx->thisObject()); + ScopedObject o(scope, callData->thisObject); if (!o) { - if (!ctx->thisObject().isUndefined()) - return Encode::undefined(); - o = ctx->d()->engine->globalObject; + if (!callData->thisObject.isUndefined()) + RETURN_UNDEFINED(); + o = scope.engine->globalObject; } ScopedProperty pd(scope); pd->value = f; pd->set = Primitive::emptyValue(); o->__defineOwnProperty__(scope.engine, prop, pd, Attr_Accessor); - return Encode::undefined(); + RETURN_UNDEFINED(); } -ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx) +void ObjectPrototype::method_defineSetter(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() < 2) - return ctx->engine()->throwTypeError(); + if (callData->argc < 2) + THROW_TYPE_ERROR(); - Scope scope(ctx); - ScopedFunctionObject f(scope, ctx->argument(1)); + ScopedFunctionObject f(scope, callData->argument(1)); if (!f) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - ScopedString prop(scope, ctx->argument(0), ScopedString::Convert); - if (scope.engine->hasException) - return Encode::undefined(); + ScopedString prop(scope, callData->argument(0), ScopedString::Convert); + CHECK_EXCEPTION(); - ScopedObject o(scope, ctx->thisObject()); + ScopedObject o(scope, callData->thisObject); if (!o) { - if (!ctx->thisObject().isUndefined()) - return Encode::undefined(); - o = ctx->d()->engine->globalObject; + if (!callData->thisObject.isUndefined()) + RETURN_UNDEFINED(); + o = scope.engine->globalObject; } ScopedProperty pd(scope); pd->value = Primitive::emptyValue(); pd->set = f; o->__defineOwnProperty__(scope.engine, prop, pd, Attr_Accessor); - return Encode::undefined(); + RETURN_UNDEFINED(); } -ReturnedValue ObjectPrototype::method_get_proto(CallContext *ctx) +void ObjectPrototype::method_get_proto(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject o(scope, ctx->thisObject().as()); + ScopedObject o(scope, callData->thisObject.as()); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - return o->prototype()->asReturnedValue(); + scope.result = o->prototype(); } -ReturnedValue ObjectPrototype::method_set_proto(CallContext *ctx) +void ObjectPrototype::method_set_proto(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject o(scope, ctx->thisObject()); - if (!o || !ctx->argc()) - return ctx->engine()->throwTypeError(); + ScopedObject o(scope, callData->thisObject); + if (!o || !callData->argc) + THROW_TYPE_ERROR(); - if (ctx->args()[0].isNull()) { + if (callData->args[0].isNull()) { o->setPrototype(0); - return Encode::undefined(); + RETURN_UNDEFINED(); } - ScopedObject p(scope, ctx->args()[0]); + ScopedObject p(scope, callData->args[0]); bool ok = false; if (!!p) { if (o->prototype() == p->d()) { @@ -562,9 +558,11 @@ ReturnedValue ObjectPrototype::method_set_proto(CallContext *ctx) ok = o->setPrototype(p); } } - if (!ok) - return ctx->engine()->throwTypeError(QStringLiteral("Cyclic __proto__ value")); - return Encode::undefined(); + if (!ok) { + scope.result = scope.engine->throwTypeError(QStringLiteral("Cyclic __proto__ value")); + return; + } + RETURN_UNDEFINED(); } void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value &v, Property *desc, PropertyAttributes *attrs) diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h index e3d85782d5..1db8615511 100644 --- a/src/qml/jsruntime/qv4objectproto_p.h +++ b/src/qml/jsruntime/qv4objectproto_p.h @@ -78,32 +78,32 @@ struct ObjectPrototype: Object { void init(ExecutionEngine *engine, Object *ctor); - static ReturnedValue method_getPrototypeOf(CallContext *ctx); - static ReturnedValue method_getOwnPropertyDescriptor(CallContext *ctx); - static ReturnedValue method_getOwnPropertyNames(CallContext *context); - static ReturnedValue method_create(CallContext *ctx); - static ReturnedValue method_defineProperty(CallContext *ctx); - static ReturnedValue method_defineProperties(CallContext *ctx); - static ReturnedValue method_seal(CallContext *ctx); - static ReturnedValue method_freeze(CallContext *ctx); - static ReturnedValue method_preventExtensions(CallContext *ctx); - static ReturnedValue method_isSealed(CallContext *ctx); - static ReturnedValue method_isFrozen(CallContext *ctx); - static ReturnedValue method_isExtensible(CallContext *ctx); - static ReturnedValue method_keys(CallContext *ctx); - - static ReturnedValue method_toString(CallContext *ctx); - static ReturnedValue method_toLocaleString(CallContext *ctx); - static ReturnedValue method_valueOf(CallContext *ctx); - static ReturnedValue method_hasOwnProperty(CallContext *ctx); - static ReturnedValue method_isPrototypeOf(CallContext *ctx); - static ReturnedValue method_propertyIsEnumerable(CallContext *ctx); - - static ReturnedValue method_defineGetter(CallContext *ctx); - static ReturnedValue method_defineSetter(CallContext *ctx); - - static ReturnedValue method_get_proto(CallContext *ctx); - static ReturnedValue method_set_proto(CallContext *ctx); + static void method_getPrototypeOf(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getOwnPropertyDescriptor(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getOwnPropertyNames(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_create(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_defineProperty(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_defineProperties(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_seal(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_freeze(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_preventExtensions(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_isSealed(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_isFrozen(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_isExtensible(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_keys(const BuiltinFunction *, Scope &scope, CallData *callData); + + static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_hasOwnProperty(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_isPrototypeOf(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_propertyIsEnumerable(const BuiltinFunction *, Scope &scope, CallData *callData); + + static void method_defineGetter(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_defineSetter(const BuiltinFunction *, Scope &scope, CallData *callData); + + static void method_get_proto(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_set_proto(const BuiltinFunction *, Scope &scope, CallData *callData); static void toPropertyDescriptor(ExecutionEngine *engine, const Value &v, Property *desc, PropertyAttributes *attrs); static ReturnedValue fromPropertyDescriptor(ExecutionEngine *engine, const Property *desc, PropertyAttributes attrs); diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 4e627e003f..379c3babda 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -68,6 +68,32 @@ namespace QV4 { struct ScopedValue; +#define CHECK_EXCEPTION() \ + do { \ + if (scope.hasException()) { \ + scope.result = Encode::undefined(); \ + return; \ + } \ + } while (false) + +#define RETURN_UNDEFINED() \ + do { \ + scope.result = Encode::undefined(); \ + return; \ + } while (false) + +#define RETURN_RESULT(r) \ + do { \ + scope.result = r; \ + return; \ + } while (false) + +#define THROW_TYPE_ERROR() \ + do { \ + scope.result = scope.engine->throwTypeError(); \ + return; \ + } while (false) + struct Scope { inline Scope(ExecutionContext *ctx) : engine(ctx->d()->engine) diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 622359a7d9..b9183313cd 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -347,6 +347,10 @@ Param traceParam(const Param ¶m) goto catchException; \ VALUE(param) = tmp; \ } +// qv4scopedvalue_p.h also defines a CHECK_EXCEPTION macro +#ifdef CHECK_EXCEPTION +#undef CHECK_EXCEPTION +#endif #define CHECK_EXCEPTION \ if (engine->hasException) \ goto catchException -- cgit v1.2.3 From cea4a039d713173d423c35fa56a6994a4ebefd2c Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 5 Jan 2017 13:06:23 +0100 Subject: Convert builtins in TypedArray, ArrayBuffer and DataView Change-Id: I091020406f438f2dedf9ccae950fb328f2cf5522 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4arraybuffer.cpp | 69 +++++++++--------- src/qml/jsruntime/qv4arraybuffer_p.h | 8 +-- src/qml/jsruntime/qv4dataview.cpp | 133 ++++++++++++++++------------------- src/qml/jsruntime/qv4dataview_p.h | 18 ++--- src/qml/jsruntime/qv4object.cpp | 21 ++++++ src/qml/jsruntime/qv4object_p.h | 4 ++ src/qml/jsruntime/qv4typedarray.cpp | 101 +++++++++++++------------- src/qml/jsruntime/qv4typedarray_p.h | 12 ++-- 8 files changed, 186 insertions(+), 180 deletions(-) diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index 23075aa78c..ffe9aa846f 100644 --- a/src/qml/jsruntime/qv4arraybuffer.cpp +++ b/src/qml/jsruntime/qv4arraybuffer.cpp @@ -81,16 +81,19 @@ void ArrayBufferCtor::call(const Managed *that, Scope &scope, CallData *callData construct(that, scope, callData); } -ReturnedValue ArrayBufferCtor::method_isView(CallContext *ctx) +void ArrayBufferCtor::method_isView(const BuiltinFunction *, Scope &scope, CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped a(scope, ctx->argument(0)); - if (!!a) - return Encode(true); - QV4::Scoped v(scope, ctx->argument(0)); - if (!!v) - return Encode(true); - return Encode(false); + QV4::Scoped a(scope, callData->argument(0)); + if (!!a) { + scope.result = Encode(true); + return; + } + QV4::Scoped v(scope, callData->argument(0)); + if (!!v) { + scope.result = Encode(true); + return; + } + scope.result = Encode(false); } @@ -160,54 +163,48 @@ void ArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("toString"), method_toString, 0); } -ReturnedValue ArrayBufferPrototype::method_get_byteLength(CallContext *ctx) +void ArrayBufferPrototype::method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped v(scope, ctx->thisObject()); + Scoped v(scope, callData->thisObject); if (!v) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); - return Encode(v->d()->data->size); + scope.result = Encode(v->d()->data->size); } -ReturnedValue ArrayBufferPrototype::method_slice(CallContext *ctx) +void ArrayBufferPrototype::method_slice(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped a(scope, ctx->thisObject()); + Scoped a(scope, callData->thisObject); if (!a) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); - double start = ctx->argc() > 0 ? ctx->args()[0].toInteger() : 0; - double end = (ctx->argc() < 2 || ctx->args()[1].isUndefined()) ? - a->d()->data->size : ctx->args()[1].toInteger(); - if (scope.engine->hasException) - return Encode::undefined(); + double start = callData->argc > 0 ? callData->args[0].toInteger() : 0; + double end = (callData->argc < 2 || callData->args[1].isUndefined()) ? + a->d()->data->size : callData->args[1].toInteger(); + CHECK_EXCEPTION(); double first = (start < 0) ? qMax(a->d()->data->size + start, 0.) : qMin(start, (double)a->d()->data->size); double final = (end < 0) ? qMax(a->d()->data->size + end, 0.) : qMin(end, (double)a->d()->data->size); ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor())); if (!constructor) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); - ScopedCallData callData(scope, 1); + ScopedCallData cData(scope, 1); double newLen = qMax(final - first, 0.); - callData->args[0] = QV4::Encode(newLen); - constructor->construct(scope, callData); - QV4::Scoped newBuffer(scope, scope.result.asReturnedValue()); + cData->args[0] = QV4::Encode(newLen); + constructor->construct(scope, cData); + QV4::Scoped newBuffer(scope, scope.result); if (!newBuffer || newBuffer->d()->data->size < (int)newLen) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); memcpy(newBuffer->d()->data->data(), a->d()->data->data() + (uint)first, newLen); - - return newBuffer.asReturnedValue(); } -ReturnedValue ArrayBufferPrototype::method_toString(CallContext *ctx) +void ArrayBufferPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped a(scope, ctx->thisObject()); + Scoped a(scope, callData->thisObject); if (!a) - return Encode::undefined(); - return Encode(ctx->engine()->newString(QString::fromUtf8(a->asByteArray()))); + RETURN_UNDEFINED(); + scope.result = scope.engine->newString(QString::fromUtf8(a->asByteArray())); } diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h index bc56d1ea31..4f7926d3dc 100644 --- a/src/qml/jsruntime/qv4arraybuffer_p.h +++ b/src/qml/jsruntime/qv4arraybuffer_p.h @@ -81,7 +81,7 @@ struct ArrayBufferCtor: FunctionObject static void construct(const Managed *m, Scope &scope, CallData *callData); static void call(const Managed *that, Scope &scope, CallData *callData); - static ReturnedValue method_isView(CallContext *ctx); + static void method_isView(const BuiltinFunction *, Scope &scope, CallData *callData); }; @@ -104,9 +104,9 @@ struct ArrayBufferPrototype: Object { void init(ExecutionEngine *engine, Object *ctor); - static ReturnedValue method_get_byteLength(CallContext *ctx); - static ReturnedValue method_slice(CallContext *ctx); - static ReturnedValue method_toString(CallContext *ctx); + static void method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_slice(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); }; diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp index db8376272d..a810b38f24 100644 --- a/src/qml/jsruntime/qv4dataview.cpp +++ b/src/qml/jsruntime/qv4dataview.cpp @@ -129,90 +129,84 @@ void DataViewPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("setUInt32"), method_set, 0); } -ReturnedValue DataViewPrototype::method_get_buffer(CallContext *ctx) +void DataViewPrototype::method_get_buffer(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped v(scope, ctx->thisObject()); + Scoped v(scope, callData->thisObject); if (!v) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); - return Encode(v->d()->buffer->asReturnedValue()); + scope.result = v->d()->buffer; } -ReturnedValue DataViewPrototype::method_get_byteLength(CallContext *ctx) +void DataViewPrototype::method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped v(scope, ctx->thisObject()); + Scoped v(scope, callData->thisObject); if (!v) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); - return Encode(v->d()->byteLength); + scope.result = Encode(v->d()->byteLength); } -ReturnedValue DataViewPrototype::method_get_byteOffset(CallContext *ctx) +void DataViewPrototype::method_get_byteOffset(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped v(scope, ctx->thisObject()); + Scoped v(scope, callData->thisObject); if (!v) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); - return Encode(v->d()->byteOffset); + scope.result = Encode(v->d()->byteOffset); } template -ReturnedValue DataViewPrototype::method_getChar(CallContext *ctx) +void DataViewPrototype::method_getChar(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped v(scope, ctx->thisObject()); - if (!v || ctx->argc() < 1) - return scope.engine->throwTypeError(); - double l = ctx->args()[0].toNumber(); + Scoped v(scope, callData->thisObject); + if (!v || callData->argc < 1) + THROW_TYPE_ERROR(); + double l = callData->args[0].toNumber(); uint idx = (uint)l; if (l != idx || idx + sizeof(T) > v->d()->byteLength) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); idx += v->d()->byteOffset; T t = T(v->d()->buffer->data->data()[idx]); - return Encode((int)t); + scope.result = Encode((int)t); } template -ReturnedValue DataViewPrototype::method_get(CallContext *ctx) +void DataViewPrototype::method_get(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped v(scope, ctx->thisObject()); - if (!v || ctx->argc() < 1) - return scope.engine->throwTypeError(); - double l = ctx->args()[0].toNumber(); + Scoped v(scope, callData->thisObject); + if (!v || callData->argc < 1) + THROW_TYPE_ERROR(); + double l = callData->args[0].toNumber(); uint idx = (uint)l; if (l != idx || idx + sizeof(T) > v->d()->byteLength) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); idx += v->d()->byteOffset; - bool littleEndian = ctx->argc() < 2 ? false : ctx->args()[1].toBoolean(); + bool littleEndian = callData->argc < 2 ? false : callData->args[1].toBoolean(); T t = littleEndian ? qFromLittleEndian((uchar *)v->d()->buffer->data->data() + idx) : qFromBigEndian((uchar *)v->d()->buffer->data->data() + idx); - return Encode(t); + scope.result = Encode(t); } template -ReturnedValue DataViewPrototype::method_getFloat(CallContext *ctx) +void DataViewPrototype::method_getFloat(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped v(scope, ctx->thisObject()); - if (!v || ctx->argc() < 1) - return scope.engine->throwTypeError(); - double l = ctx->args()[0].toNumber(); + Scoped v(scope, callData->thisObject); + if (!v || callData->argc < 1) + THROW_TYPE_ERROR(); + double l = callData->args[0].toNumber(); uint idx = (uint)l; if (l != idx || idx + sizeof(T) > v->d()->byteLength) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); idx += v->d()->byteOffset; - bool littleEndian = ctx->argc() < 2 ? false : ctx->args()[1].toBoolean(); + bool littleEndian = callData->argc < 2 ? false : callData->args[1].toBoolean(); if (sizeof(T) == 4) { // float @@ -223,7 +217,7 @@ ReturnedValue DataViewPrototype::method_getFloat(CallContext *ctx) u.i = littleEndian ? qFromLittleEndian((uchar *)v->d()->buffer->data->data() + idx) : qFromBigEndian((uchar *)v->d()->buffer->data->data() + idx); - return Encode(u.f); + scope.result = Encode(u.f); } else { Q_ASSERT(sizeof(T) == 8); union { @@ -233,69 +227,66 @@ ReturnedValue DataViewPrototype::method_getFloat(CallContext *ctx) u.i = littleEndian ? qFromLittleEndian((uchar *)v->d()->buffer->data->data() + idx) : qFromBigEndian((uchar *)v->d()->buffer->data->data() + idx); - return Encode(u.d); + scope.result = Encode(u.d); } } template -ReturnedValue DataViewPrototype::method_setChar(CallContext *ctx) +void DataViewPrototype::method_setChar(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped v(scope, ctx->thisObject()); - if (!v || ctx->argc() < 1) - return scope.engine->throwTypeError(); - double l = ctx->args()[0].toNumber(); + Scoped v(scope, callData->thisObject); + if (!v || callData->argc < 1) + THROW_TYPE_ERROR(); + double l = callData->args[0].toNumber(); uint idx = (uint)l; if (l != idx || idx + sizeof(T) > v->d()->byteLength) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); idx += v->d()->byteOffset; - int val = ctx->argc() >= 2 ? ctx->args()[1].toInt32() : 0; + int val = callData->argc >= 2 ? callData->args[1].toInt32() : 0; v->d()->buffer->data->data()[idx] = (char)val; - return Encode::undefined(); + RETURN_UNDEFINED(); } template -ReturnedValue DataViewPrototype::method_set(CallContext *ctx) +void DataViewPrototype::method_set(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped v(scope, ctx->thisObject()); - if (!v || ctx->argc() < 1) - return scope.engine->throwTypeError(); - double l = ctx->args()[0].toNumber(); + Scoped v(scope, callData->thisObject); + if (!v || callData->argc < 1) + THROW_TYPE_ERROR(); + double l = callData->args[0].toNumber(); uint idx = (uint)l; if (l != idx || idx + sizeof(T) > v->d()->byteLength) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); idx += v->d()->byteOffset; - int val = ctx->argc() >= 2 ? ctx->args()[1].toInt32() : 0; + int val = callData->argc >= 2 ? callData->args[1].toInt32() : 0; - bool littleEndian = ctx->argc() < 3 ? false : ctx->args()[2].toBoolean(); + bool littleEndian = callData->argc < 3 ? false : callData->args[2].toBoolean(); if (littleEndian) qToLittleEndian(val, (uchar *)v->d()->buffer->data->data() + idx); else qToBigEndian(val, (uchar *)v->d()->buffer->data->data() + idx); - return Encode::undefined(); + RETURN_UNDEFINED(); } template -ReturnedValue DataViewPrototype::method_setFloat(CallContext *ctx) +void DataViewPrototype::method_setFloat(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped v(scope, ctx->thisObject()); - if (!v || ctx->argc() < 1) - return scope.engine->throwTypeError(); - double l = ctx->args()[0].toNumber(); + Scoped v(scope, callData->thisObject); + if (!v || callData->argc < 1) + THROW_TYPE_ERROR(); + double l = callData->args[0].toNumber(); uint idx = (uint)l; if (l != idx || idx + sizeof(T) > v->d()->byteLength) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); idx += v->d()->byteOffset; - double val = ctx->argc() >= 2 ? ctx->args()[1].toNumber() : qt_qnan(); - bool littleEndian = ctx->argc() < 3 ? false : ctx->args()[2].toBoolean(); + double val = callData->argc >= 2 ? callData->args[1].toNumber() : qt_qnan(); + bool littleEndian = callData->argc < 3 ? false : callData->args[2].toBoolean(); if (sizeof(T) == 4) { // float @@ -320,5 +311,5 @@ ReturnedValue DataViewPrototype::method_setFloat(CallContext *ctx) else qToBigEndian(u.i, (uchar *)v->d()->buffer->data->data() + idx); } - return Encode::undefined(); + RETURN_UNDEFINED(); } diff --git a/src/qml/jsruntime/qv4dataview_p.h b/src/qml/jsruntime/qv4dataview_p.h index 246124394a..11cc0a6bd9 100644 --- a/src/qml/jsruntime/qv4dataview_p.h +++ b/src/qml/jsruntime/qv4dataview_p.h @@ -92,21 +92,21 @@ struct DataViewPrototype: Object { void init(ExecutionEngine *engine, Object *ctor); - static ReturnedValue method_get_buffer(CallContext *ctx); - static ReturnedValue method_get_byteLength(CallContext *ctx); - static ReturnedValue method_get_byteOffset(CallContext *ctx); + static void method_get_buffer(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_get_byteOffset(const BuiltinFunction *, Scope &scope, CallData *callData); template - static ReturnedValue method_getChar(CallContext *ctx); + static void method_getChar(const BuiltinFunction *, Scope &scope, CallData *callData); template - static ReturnedValue method_get(CallContext *ctx); + static void method_get(const BuiltinFunction *, Scope &scope, CallData *callData); template - static ReturnedValue method_getFloat(CallContext *ctx); + static void method_getFloat(const BuiltinFunction *, Scope &scope, CallData *callData); template - static ReturnedValue method_setChar(CallContext *ctx); + static void method_setChar(const BuiltinFunction *, Scope &scope, CallData *callData); template - static ReturnedValue method_set(CallContext *ctx); + static void method_set(const BuiltinFunction *, Scope &scope, CallData *callData); template - static ReturnedValue method_setFloat(CallContext *ctx); + static void method_setFloat(const BuiltinFunction *, Scope &scope, CallData *callData); }; diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index cb13069ca0..5d6c479477 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -216,6 +216,27 @@ void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(CallCo insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); } +void Object::defineAccessorProperty(const QString &name, void (*getter)(const BuiltinFunction *, Scope &, CallData *), + void (*setter)(const BuiltinFunction *, Scope &, CallData *)) +{ + ExecutionEngine *e = engine(); + Scope scope(e); + ScopedString s(scope, e->newIdentifier(name)); + defineAccessorProperty(s, getter, setter); +} + +void Object::defineAccessorProperty(String *name, void (*getter)(const BuiltinFunction *, Scope &, CallData *), + void (*setter)(const BuiltinFunction *, Scope &, CallData *)) +{ + ExecutionEngine *v4 = engine(); + QV4::Scope scope(v4); + ScopedProperty p(scope); + ExecutionContext *global = v4->rootContext(); + p->setGetter(ScopedFunctionObject(scope, (getter ? BuiltinFunction::create(global, name, getter) : 0))); + p->setSetter(ScopedFunctionObject(scope, (setter ? BuiltinFunction::create(global, name, setter) : 0))); + insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); +} + void Object::defineReadonlyProperty(const QString &name, const Value &value) { QV4::ExecutionEngine *e = engine(); diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index cf9d7bbcdf..4a78690f47 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -243,6 +243,10 @@ struct Q_QML_EXPORT Object: Managed { void defineDefaultProperty(String *name, void (*code)(const BuiltinFunction *, Scope &, CallData *), int argumentCount = 0); void defineAccessorProperty(const QString &name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *)); void defineAccessorProperty(String *name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *)); + void defineAccessorProperty(const QString &name, void (*getter)(const BuiltinFunction *, Scope &, CallData *), + void (*setter)(const BuiltinFunction *, Scope &, CallData *)); + void defineAccessorProperty(String *name, void (*getter)(const BuiltinFunction *, Scope &, CallData *), + void (*setter)(const BuiltinFunction *, Scope &, CallData *)); /* Fixed: Writable: false, Enumerable: false, Configurable: false */ void defineReadonlyProperty(const QString &name, const Value &value); void defineReadonlyProperty(String *name, const Value &value); diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index 009c573bf8..cecd1e6958 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -438,79 +438,74 @@ void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor) defineDefaultProperty(QStringLiteral("subarray"), method_subarray, 0); } -ReturnedValue TypedArrayPrototype::method_get_buffer(CallContext *ctx) +void TypedArrayPrototype::method_get_buffer(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped v(scope, ctx->thisObject()); + Scoped v(scope, callData->thisObject); if (!v) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); - return Encode(v->d()->buffer->asReturnedValue()); + scope.result = v->d()->buffer; } -ReturnedValue TypedArrayPrototype::method_get_byteLength(CallContext *ctx) +void TypedArrayPrototype::method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped v(scope, ctx->thisObject()); + Scoped v(scope, callData->thisObject); if (!v) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); - return Encode(v->d()->byteLength); + scope.result = Encode(v->d()->byteLength); } -ReturnedValue TypedArrayPrototype::method_get_byteOffset(CallContext *ctx) +void TypedArrayPrototype::method_get_byteOffset(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped v(scope, ctx->thisObject()); + Scoped v(scope, callData->thisObject); if (!v) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); - return Encode(v->d()->byteOffset); + scope.result = Encode(v->d()->byteOffset); } -ReturnedValue TypedArrayPrototype::method_get_length(CallContext *ctx) +void TypedArrayPrototype::method_get_length(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped v(scope, ctx->thisObject()); + Scoped v(scope, callData->thisObject); if (!v) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); - return Encode(v->d()->byteLength/v->d()->type->bytesPerElement); + scope.result = Encode(v->d()->byteLength/v->d()->type->bytesPerElement); } -ReturnedValue TypedArrayPrototype::method_set(CallContext *ctx) +void TypedArrayPrototype::method_set(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped a(scope, ctx->thisObject()); + Scoped a(scope, callData->thisObject); if (!a) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); Scoped buffer(scope, a->d()->buffer); if (!buffer) scope.engine->throwTypeError(); - double doffset = ctx->argc() >= 2 ? ctx->args()[1].toInteger() : 0; + double doffset = callData->argc >= 2 ? callData->args[1].toInteger() : 0; if (scope.engine->hasException) - return Encode::undefined(); + RETURN_UNDEFINED(); if (doffset < 0 || doffset >= UINT_MAX) - return scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range")); + RETURN_RESULT(scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range"))); uint offset = (uint)doffset; uint elementSize = a->d()->type->bytesPerElement; - Scoped srcTypedArray(scope, ctx->args()[0]); + Scoped srcTypedArray(scope, callData->args[0]); if (!srcTypedArray) { // src is a regular object - ScopedObject o(scope, ctx->args()[0].toObject(scope.engine)); + ScopedObject o(scope, callData->args[0].toObject(scope.engine)); if (scope.engine->hasException || !o) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); double len = ScopedValue(scope, o->get(scope.engine->id_length()))->toNumber(); uint l = (uint)len; if (scope.engine->hasException || l != len) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); if (offset + l > a->length()) - return scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range")); + RETURN_RESULT(scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range"))); uint idx = 0; char *b = buffer->d()->data->data() + a->d()->byteOffset + offset*elementSize; @@ -519,28 +514,28 @@ ReturnedValue TypedArrayPrototype::method_set(CallContext *ctx) val = o->getIndexed(idx); a->d()->type->write(scope.engine, b, 0, val); if (scope.engine->hasException) - return Encode::undefined(); + RETURN_UNDEFINED(); ++idx; b += elementSize; } - return Encode::undefined(); + RETURN_UNDEFINED(); } // src is a typed array Scoped srcBuffer(scope, srcTypedArray->d()->buffer); if (!srcBuffer) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); uint l = srcTypedArray->length(); if (offset + l > a->length()) - return scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range")); + RETURN_RESULT(scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range"))); char *dest = buffer->d()->data->data() + a->d()->byteOffset + offset*elementSize; const char *src = srcBuffer->d()->data->data() + srcTypedArray->d()->byteOffset; if (srcTypedArray->d()->type == a->d()->type) { // same type of typed arrays, use memmove (as srcbuffer and buffer could be the same) memmove(dest, src, srcTypedArray->d()->byteLength); - return Encode::undefined(); + RETURN_UNDEFINED(); } char *srcCopy = 0; @@ -564,28 +559,27 @@ ReturnedValue TypedArrayPrototype::method_set(CallContext *ctx) if (srcCopy) delete [] srcCopy; - return Encode::undefined(); + RETURN_UNDEFINED(); } -ReturnedValue TypedArrayPrototype::method_subarray(CallContext *ctx) +void TypedArrayPrototype::method_subarray(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped a(scope, ctx->thisObject()); + Scoped a(scope, callData->thisObject); if (!a) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); Scoped buffer(scope, a->d()->buffer); if (!buffer) - return scope.engine->throwTypeError(); + THROW_TYPE_ERROR(); int len = a->length(); - double b = ctx->argc() > 0 ? ctx->args()[0].toInteger() : 0; + double b = callData->argc > 0 ? callData->args[0].toInteger() : 0; if (b < 0) b = len + b; uint begin = (uint)qBound(0., b, (double)len); - double e = ctx->argc() < 2 || ctx->args()[1].isUndefined() ? len : ctx->args()[1].toInteger(); + double e = callData->argc < 2 || callData->args[1].isUndefined() ? len : callData->args[1].toInteger(); if (e < 0) e = len + e; uint end = (uint)qBound(0., e, (double)len); @@ -593,18 +587,17 @@ ReturnedValue TypedArrayPrototype::method_subarray(CallContext *ctx) end = begin; if (scope.engine->hasException) - return Encode::undefined(); + RETURN_UNDEFINED(); int newLen = end - begin; ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor())); if (!constructor) - return scope.engine->throwTypeError(); - - ScopedCallData callData(scope, 3); - callData->args[0] = buffer; - callData->args[1] = Encode(a->d()->byteOffset + begin*a->d()->type->bytesPerElement); - callData->args[2] = Encode(newLen); - constructor->construct(scope, callData); - return scope.result.asReturnedValue(); + THROW_TYPE_ERROR(); + + ScopedCallData cData(scope, 3); + cData->args[0] = buffer; + cData->args[1] = Encode(a->d()->byteOffset + begin*a->d()->type->bytesPerElement); + cData->args[2] = Encode(newLen); + constructor->construct(scope, cData); } diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h index 0112d2e4a1..eefed2db4b 100644 --- a/src/qml/jsruntime/qv4typedarray_p.h +++ b/src/qml/jsruntime/qv4typedarray_p.h @@ -151,13 +151,13 @@ struct TypedArrayPrototype : Object void init(ExecutionEngine *engine, TypedArrayCtor *ctor); - static ReturnedValue method_get_buffer(CallContext *ctx); - static ReturnedValue method_get_byteLength(CallContext *ctx); - static ReturnedValue method_get_byteOffset(CallContext *ctx); - static ReturnedValue method_get_length(CallContext *ctx); + static void method_get_buffer(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_get_byteLength(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_get_byteOffset(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_get_length(const BuiltinFunction *, Scope &scope, CallData *callData); - static ReturnedValue method_set(CallContext *ctx); - static ReturnedValue method_subarray(CallContext *ctx); + static void method_set(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_subarray(const BuiltinFunction *, Scope &scope, CallData *callData); }; inline void -- cgit v1.2.3 From afc29a54791e70264f7c175b2da0a234f791f749 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 5 Jan 2017 13:39:38 +0100 Subject: Convert more builtin methods to the new calling convention Change-Id: I2cd1df437d91918001beed8dfe92d553b3bb377f Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4booleanobject.cpp | 26 +- src/qml/jsruntime/qv4booleanobject_p.h | 4 +- src/qml/jsruntime/qv4dateobject.cpp | 475 ++++++++++++++++---------------- src/qml/jsruntime/qv4dateobject_p.h | 102 +++---- src/qml/jsruntime/qv4numberobject.cpp | 160 ++++++----- src/qml/jsruntime/qv4numberobject_p.h | 16 +- src/qml/jsruntime/qv4stringobject.cpp | 395 +++++++++++++-------------- src/qml/jsruntime/qv4stringobject_p.h | 46 ++-- src/qml/qml/qqmllocale.cpp | 485 +++++++++++++++++---------------- src/qml/qml/qqmllocale_p.h | 82 +++--- 10 files changed, 891 insertions(+), 900 deletions(-) diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp index 8047993266..601066110f 100644 --- a/src/qml/jsruntime/qv4booleanobject.cpp +++ b/src/qml/jsruntime/qv4booleanobject.cpp @@ -73,29 +73,31 @@ void BooleanPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(engine->id_valueOf(), method_valueOf); } -ReturnedValue BooleanPrototype::method_toString(CallContext *ctx) +void BooleanPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) { bool result; - if (ctx->thisObject().isBoolean()) { - result = ctx->thisObject().booleanValue(); + if (callData->thisObject.isBoolean()) { + result = callData->thisObject.booleanValue(); } else { - const BooleanObject *thisObject = ctx->thisObject().as(); + const BooleanObject *thisObject = callData->thisObject.as(); if (!thisObject) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); result = thisObject->value(); } - return Encode(ctx->d()->engine->newString(QLatin1String(result ? "true" : "false"))); + scope.result = scope.engine->newString(QLatin1String(result ? "true" : "false")); } -ReturnedValue BooleanPrototype::method_valueOf(CallContext *ctx) +void BooleanPrototype::method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->thisObject().isBoolean()) - return ctx->thisObject().asReturnedValue(); + if (callData->thisObject.isBoolean()) { + scope.result = callData->thisObject.asReturnedValue(); + return; + } - const BooleanObject *thisObject = ctx->thisObject().as(); + const BooleanObject *thisObject = callData->thisObject.as(); if (!thisObject) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - return Encode(thisObject->value()); + scope.result = Encode(thisObject->value()); } diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h index 4c2f3c09e7..9c8b1d67f1 100644 --- a/src/qml/jsruntime/qv4booleanobject_p.h +++ b/src/qml/jsruntime/qv4booleanobject_p.h @@ -78,8 +78,8 @@ struct BooleanPrototype: BooleanObject { void init(ExecutionEngine *engine, Object *ctor); - static ReturnedValue method_toString(CallContext *ctx); - static ReturnedValue method_valueOf(CallContext *ctx); + static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData); }; diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 8cc6a25fea..b90c335b1c 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -780,435 +780,435 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("toJSON"), method_toJSON, 1); } -double DatePrototype::getThisDate(ExecutionContext *ctx) +double DatePrototype::getThisDate(Scope &scope, CallData *callData) { - if (DateObject *thisObject = ctx->thisObject().as()) + if (DateObject *thisObject = callData->thisObject.as()) return thisObject->date(); else { - ctx->engine()->throwTypeError(); + scope.engine->throwTypeError(); return 0; } } -ReturnedValue DatePrototype::method_parse(CallContext *ctx) +void DatePrototype::method_parse(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (!ctx->argc()) - return Encode(qt_qnan()); - return Encode(ParseString(ctx->args()[0].toQString())); + if (!callData->argc) + scope.result = Encode(qt_qnan()); + else + scope.result = Encode(ParseString(callData->args[0].toQString())); } -ReturnedValue DatePrototype::method_UTC(CallContext *ctx) +void DatePrototype::method_UTC(const BuiltinFunction *, Scope &scope, CallData *callData) { - const int numArgs = ctx->argc(); + const int numArgs = callData->argc; if (numArgs >= 2) { - double year = ctx->args()[0].toNumber(); - double month = ctx->args()[1].toNumber(); - double day = numArgs >= 3 ? ctx->args()[2].toNumber() : 1; - double hours = numArgs >= 4 ? ctx->args()[3].toNumber() : 0; - double mins = numArgs >= 5 ? ctx->args()[4].toNumber() : 0; - double secs = numArgs >= 6 ? ctx->args()[5].toNumber() : 0; - double ms = numArgs >= 7 ? ctx->args()[6].toNumber() : 0; + double year = callData->args[0].toNumber(); + double month = callData->args[1].toNumber(); + double day = numArgs >= 3 ? callData->args[2].toNumber() : 1; + double hours = numArgs >= 4 ? callData->args[3].toNumber() : 0; + double mins = numArgs >= 5 ? callData->args[4].toNumber() : 0; + double secs = numArgs >= 6 ? callData->args[5].toNumber() : 0; + double ms = numArgs >= 7 ? callData->args[6].toNumber() : 0; if (year >= 0 && year <= 99) year += 1900; double t = MakeDate(MakeDay(year, month, day), MakeTime(hours, mins, secs, ms)); - return Encode(TimeClip(t)); + scope.result = Encode(TimeClip(t)); + return; } - return Encode::undefined(); + RETURN_UNDEFINED(); } -ReturnedValue DatePrototype::method_now(CallContext *ctx) +void DatePrototype::method_now(const BuiltinFunction *, Scope &scope, CallData *callData) { - Q_UNUSED(ctx); + Q_UNUSED(callData); double t = currentTime(); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_toString(CallContext *ctx) +void DatePrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - return ctx->d()->engine->newString(ToString(t))->asReturnedValue(); + double t = getThisDate(scope, callData); + scope.result = scope.engine->newString(ToString(t)); } -ReturnedValue DatePrototype::method_toDateString(CallContext *ctx) +void DatePrototype::method_toDateString(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - return ctx->d()->engine->newString(ToDateString(t))->asReturnedValue(); + double t = getThisDate(scope, callData); + scope.result = scope.engine->newString(ToDateString(t)); } -ReturnedValue DatePrototype::method_toTimeString(CallContext *ctx) +void DatePrototype::method_toTimeString(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - return ctx->d()->engine->newString(ToTimeString(t))->asReturnedValue(); + double t = getThisDate(scope, callData); + scope.result = scope.engine->newString(ToTimeString(t)); } -ReturnedValue DatePrototype::method_toLocaleString(CallContext *ctx) +void DatePrototype::method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - return ctx->d()->engine->newString(ToLocaleString(t))->asReturnedValue(); + double t = getThisDate(scope, callData); + scope.result = scope.engine->newString(ToLocaleString(t)); } -ReturnedValue DatePrototype::method_toLocaleDateString(CallContext *ctx) +void DatePrototype::method_toLocaleDateString(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - return ctx->d()->engine->newString(ToLocaleDateString(t))->asReturnedValue(); + double t = getThisDate(scope, callData); + scope.result = scope.engine->newString(ToLocaleDateString(t)); } -ReturnedValue DatePrototype::method_toLocaleTimeString(CallContext *ctx) +void DatePrototype::method_toLocaleTimeString(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - return ctx->d()->engine->newString(ToLocaleTimeString(t))->asReturnedValue(); + double t = getThisDate(scope, callData); + scope.result = scope.engine->newString(ToLocaleTimeString(t)); } -ReturnedValue DatePrototype::method_valueOf(CallContext *ctx) +void DatePrototype::method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - return Encode(t); + double t = getThisDate(scope, callData); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getTime(CallContext *ctx) +void DatePrototype::method_getTime(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - return Encode(t); + double t = getThisDate(scope, callData); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getYear(CallContext *ctx) +void DatePrototype::method_getYear(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = YearFromTime(LocalTime(t)) - 1900; - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getFullYear(CallContext *ctx) +void DatePrototype::method_getFullYear(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = YearFromTime(LocalTime(t)); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getUTCFullYear(CallContext *ctx) +void DatePrototype::method_getUTCFullYear(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = YearFromTime(t); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getMonth(CallContext *ctx) +void DatePrototype::method_getMonth(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = MonthFromTime(LocalTime(t)); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getUTCMonth(CallContext *ctx) +void DatePrototype::method_getUTCMonth(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = MonthFromTime(t); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getDate(CallContext *ctx) +void DatePrototype::method_getDate(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = DateFromTime(LocalTime(t)); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getUTCDate(CallContext *ctx) +void DatePrototype::method_getUTCDate(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = DateFromTime(t); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getDay(CallContext *ctx) +void DatePrototype::method_getDay(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = WeekDay(LocalTime(t)); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getUTCDay(CallContext *ctx) +void DatePrototype::method_getUTCDay(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = WeekDay(t); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getHours(CallContext *ctx) +void DatePrototype::method_getHours(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = HourFromTime(LocalTime(t)); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getUTCHours(CallContext *ctx) +void DatePrototype::method_getUTCHours(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = HourFromTime(t); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getMinutes(CallContext *ctx) +void DatePrototype::method_getMinutes(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = MinFromTime(LocalTime(t)); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getUTCMinutes(CallContext *ctx) +void DatePrototype::method_getUTCMinutes(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = MinFromTime(t); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getSeconds(CallContext *ctx) +void DatePrototype::method_getSeconds(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = SecFromTime(LocalTime(t)); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getUTCSeconds(CallContext *ctx) +void DatePrototype::method_getUTCSeconds(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = SecFromTime(t); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getMilliseconds(CallContext *ctx) +void DatePrototype::method_getMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = msFromTime(LocalTime(t)); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getUTCMilliseconds(CallContext *ctx) +void DatePrototype::method_getUTCMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = msFromTime(t); - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_getTimezoneOffset(CallContext *ctx) +void DatePrototype::method_getTimezoneOffset(const BuiltinFunction *, Scope &scope, CallData *callData) { - double t = getThisDate(ctx); - if (! std::isnan(t)) + double t = getThisDate(scope, callData); + if (!std::isnan(t)) t = (t - LocalTime(t)) / msPerMinute; - return Encode(t); + scope.result = Encode(t); } -ReturnedValue DatePrototype::method_setTime(CallContext *ctx) +void DatePrototype::method_setTime(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped self(scope, ctx->thisObject()); + Scoped self(scope, callData->thisObject); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - double t = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); + double t = callData->argc ? callData->args[0].toNumber() : qt_qnan(); self->setDate(TimeClip(t)); - return Encode(self->date()); + scope.result = Encode(self->date()); } -ReturnedValue DatePrototype::method_setMilliseconds(CallContext *ctx) +void DatePrototype::method_setMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped self(scope, ctx->thisObject()); + Scoped self(scope, callData->thisObject); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = LocalTime(self->date()); - double ms = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); + double ms = callData->argc ? callData->args[0].toNumber() : qt_qnan(); self->setDate(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))))); - return Encode(self->date()); + scope.result = Encode(self->date()); } -ReturnedValue DatePrototype::method_setUTCMilliseconds(CallContext *ctx) +void DatePrototype::method_setUTCMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData) { - DateObject *self = ctx->thisObject().as(); + DateObject *self = callData->thisObject.as(); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = self->date(); - double ms = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); + double ms = callData->argc ? callData->args[0].toNumber() : qt_qnan(); self->setDate(TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))); - return Encode(self->date()); + scope.result = Encode(self->date()); } -ReturnedValue DatePrototype::method_setSeconds(CallContext *ctx) +void DatePrototype::method_setSeconds(const BuiltinFunction *, Scope &scope, CallData *callData) { - DateObject *self = ctx->thisObject().as(); + DateObject *self = callData->thisObject.as(); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = LocalTime(self->date()); - double sec = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); - double ms = (ctx->argc() < 2) ? msFromTime(t) : ctx->args()[1].toNumber(); + double sec = callData->argc ? callData->args[0].toNumber() : qt_qnan(); + double ms = (callData->argc < 2) ? msFromTime(t) : callData->args[1].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)))); self->setDate(t); - return Encode(self->date()); + scope.result = Encode(self->date()); } -ReturnedValue DatePrototype::method_setUTCSeconds(CallContext *ctx) +void DatePrototype::method_setUTCSeconds(const BuiltinFunction *, Scope &scope, CallData *callData) { - DateObject *self = ctx->thisObject().as(); + DateObject *self = callData->thisObject.as(); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = self->date(); - double sec = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); - double ms = (ctx->argc() < 2) ? msFromTime(t) : ctx->args()[1].toNumber(); + double sec = callData->argc ? callData->args[0].toNumber() : qt_qnan(); + double ms = (callData->argc < 2) ? msFromTime(t) : callData->args[1].toNumber(); t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms))); self->setDate(t); - return Encode(self->date()); + scope.result = Encode(self->date()); } -ReturnedValue DatePrototype::method_setMinutes(CallContext *ctx) +void DatePrototype::method_setMinutes(const BuiltinFunction *, Scope &scope, CallData *callData) { - DateObject *self = ctx->thisObject().as(); + DateObject *self = callData->thisObject.as(); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = LocalTime(self->date()); - double min = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); - double sec = (ctx->argc() < 2) ? SecFromTime(t) : ctx->args()[1].toNumber(); - double ms = (ctx->argc() < 3) ? msFromTime(t) : ctx->args()[2].toNumber(); + double min = callData->argc ? callData->args[0].toNumber() : qt_qnan(); + double sec = (callData->argc < 2) ? SecFromTime(t) : callData->args[1].toNumber(); + double ms = (callData->argc < 3) ? msFromTime(t) : callData->args[2].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)))); self->setDate(t); - return Encode(self->date()); + scope.result = Encode(self->date()); } -ReturnedValue DatePrototype::method_setUTCMinutes(CallContext *ctx) +void DatePrototype::method_setUTCMinutes(const BuiltinFunction *, Scope &scope, CallData *callData) { - DateObject *self = ctx->thisObject().as(); + DateObject *self = callData->thisObject.as(); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = self->date(); - double min = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); - double sec = (ctx->argc() < 2) ? SecFromTime(t) : ctx->args()[1].toNumber(); - double ms = (ctx->argc() < 3) ? msFromTime(t) : ctx->args()[2].toNumber(); + double min = callData->argc ? callData->args[0].toNumber() : qt_qnan(); + double sec = (callData->argc < 2) ? SecFromTime(t) : callData->args[1].toNumber(); + double ms = (callData->argc < 3) ? msFromTime(t) : callData->args[2].toNumber(); t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms))); self->setDate(t); - return Encode(self->date()); + scope.result = Encode(self->date()); } -ReturnedValue DatePrototype::method_setHours(CallContext *ctx) +void DatePrototype::method_setHours(const BuiltinFunction *, Scope &scope, CallData *callData) { - DateObject *self = ctx->thisObject().as(); + DateObject *self = callData->thisObject.as(); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = LocalTime(self->date()); - double hour = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); - double min = (ctx->argc() < 2) ? MinFromTime(t) : ctx->args()[1].toNumber(); - double sec = (ctx->argc() < 3) ? SecFromTime(t) : ctx->args()[2].toNumber(); - double ms = (ctx->argc() < 4) ? msFromTime(t) : ctx->args()[3].toNumber(); + double hour = callData->argc ? callData->args[0].toNumber() : qt_qnan(); + double min = (callData->argc < 2) ? MinFromTime(t) : callData->args[1].toNumber(); + double sec = (callData->argc < 3) ? SecFromTime(t) : callData->args[2].toNumber(); + double ms = (callData->argc < 4) ? msFromTime(t) : callData->args[3].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms)))); self->setDate(t); - return Encode(self->date()); + scope.result = Encode(self->date()); } -ReturnedValue DatePrototype::method_setUTCHours(CallContext *ctx) +void DatePrototype::method_setUTCHours(const BuiltinFunction *, Scope &scope, CallData *callData) { - DateObject *self = ctx->thisObject().as(); + DateObject *self = callData->thisObject.as(); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = self->date(); - double hour = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); - double min = (ctx->argc() < 2) ? MinFromTime(t) : ctx->args()[1].toNumber(); - double sec = (ctx->argc() < 3) ? SecFromTime(t) : ctx->args()[2].toNumber(); - double ms = (ctx->argc() < 4) ? msFromTime(t) : ctx->args()[3].toNumber(); + double hour = callData->argc ? callData->args[0].toNumber() : qt_qnan(); + double min = (callData->argc < 2) ? MinFromTime(t) : callData->args[1].toNumber(); + double sec = (callData->argc < 3) ? SecFromTime(t) : callData->args[2].toNumber(); + double ms = (callData->argc < 4) ? msFromTime(t) : callData->args[3].toNumber(); t = TimeClip(MakeDate(Day(t), MakeTime(hour, min, sec, ms))); self->setDate(t); - return Encode(self->date()); + scope.result = Encode(self->date()); } -ReturnedValue DatePrototype::method_setDate(CallContext *ctx) +void DatePrototype::method_setDate(const BuiltinFunction *, Scope &scope, CallData *callData) { - DateObject *self = ctx->thisObject().as(); + DateObject *self = callData->thisObject.as(); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = LocalTime(self->date()); - double date = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); + double date = callData->argc ? callData->args[0].toNumber() : qt_qnan(); t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t)))); self->setDate(t); - return Encode(self->date()); + scope.result = Encode(self->date()); } -ReturnedValue DatePrototype::method_setUTCDate(CallContext *ctx) +void DatePrototype::method_setUTCDate(const BuiltinFunction *, Scope &scope, CallData *callData) { - DateObject *self = ctx->thisObject().as(); + DateObject *self = callData->thisObject.as(); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = self->date(); - double date = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); + double date = callData->argc ? callData->args[0].toNumber() : qt_qnan(); t = TimeClip(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t))); self->setDate(t); - return Encode(self->date()); + scope.result = Encode(self->date()); } -ReturnedValue DatePrototype::method_setMonth(CallContext *ctx) +void DatePrototype::method_setMonth(const BuiltinFunction *, Scope &scope, CallData *callData) { - DateObject *self = ctx->thisObject().as(); + DateObject *self = callData->thisObject.as(); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = LocalTime(self->date()); - double month = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); - double date = (ctx->argc() < 2) ? DateFromTime(t) : ctx->args()[1].toNumber(); + double month = callData->argc ? callData->args[0].toNumber() : qt_qnan(); + double date = (callData->argc < 2) ? DateFromTime(t) : callData->args[1].toNumber(); t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)))); self->setDate(t); - return Encode(self->date()); + scope.result = Encode(self->date()); } -ReturnedValue DatePrototype::method_setUTCMonth(CallContext *ctx) +void DatePrototype::method_setUTCMonth(const BuiltinFunction *, Scope &scope, CallData *callData) { - DateObject *self = ctx->thisObject().as(); + DateObject *self = callData->thisObject.as(); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = self->date(); - double month = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); - double date = (ctx->argc() < 2) ? DateFromTime(t) : ctx->args()[1].toNumber(); + double month = callData->argc ? callData->args[0].toNumber() : qt_qnan(); + double date = (callData->argc < 2) ? DateFromTime(t) : callData->args[1].toNumber(); t = TimeClip(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t))); self->setDate(t); - return Encode(self->date()); + scope.result = Encode(self->date()); } -ReturnedValue DatePrototype::method_setYear(CallContext *ctx) +void DatePrototype::method_setYear(const BuiltinFunction *, Scope &scope, CallData *callData) { - DateObject *self = ctx->thisObject().as(); + DateObject *self = callData->thisObject.as(); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = self->date(); if (std::isnan(t)) t = 0; else t = LocalTime(t); - double year = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); + double year = callData->argc ? callData->args[0].toNumber() : qt_qnan(); double r; if (std::isnan(year)) { r = qt_qnan(); @@ -1220,49 +1220,49 @@ ReturnedValue DatePrototype::method_setYear(CallContext *ctx) r = TimeClip(r); } self->setDate(r); - return Encode(self->date()); + scope.result = Encode(self->date()); } -ReturnedValue DatePrototype::method_setUTCFullYear(CallContext *ctx) +void DatePrototype::method_setUTCFullYear(const BuiltinFunction *, Scope &scope, CallData *callData) { - DateObject *self = ctx->thisObject().as(); + DateObject *self = callData->thisObject.as(); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = self->date(); - double year = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); - double month = (ctx->argc() < 2) ? MonthFromTime(t) : ctx->args()[1].toNumber(); - double date = (ctx->argc() < 3) ? DateFromTime(t) : ctx->args()[2].toNumber(); + double year = callData->argc ? callData->args[0].toNumber() : qt_qnan(); + double month = (callData->argc < 2) ? MonthFromTime(t) : callData->args[1].toNumber(); + double date = (callData->argc < 3) ? DateFromTime(t) : callData->args[2].toNumber(); t = TimeClip(MakeDate(MakeDay(year, month, date), TimeWithinDay(t))); self->setDate(t); - return Encode(self->date()); + scope.result = Encode(self->date()); } -ReturnedValue DatePrototype::method_setFullYear(CallContext *ctx) +void DatePrototype::method_setFullYear(const BuiltinFunction *, Scope &scope, CallData *callData) { - DateObject *self = ctx->thisObject().as(); + DateObject *self = callData->thisObject.as(); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = LocalTime(self->date()); if (std::isnan(t)) t = 0; - double year = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); - double month = (ctx->argc() < 2) ? MonthFromTime(t) : ctx->args()[1].toNumber(); - double date = (ctx->argc() < 3) ? DateFromTime(t) : ctx->args()[2].toNumber(); + double year = callData->argc ? callData->args[0].toNumber() : qt_qnan(); + double month = (callData->argc < 2) ? MonthFromTime(t) : callData->args[1].toNumber(); + double date = (callData->argc < 3) ? DateFromTime(t) : callData->args[2].toNumber(); t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)))); self->setDate(t); - return Encode(self->date()); + scope.result = Encode(self->date()); } -ReturnedValue DatePrototype::method_toUTCString(CallContext *ctx) +void DatePrototype::method_toUTCString(const BuiltinFunction *, Scope &scope, CallData *callData) { - DateObject *self = ctx->thisObject().as(); + DateObject *self = callData->thisObject.as(); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = self->date(); - return ctx->d()->engine->newString(ToUTCString(t))->asReturnedValue(); + scope.result = scope.engine->newString(ToUTCString(t)); } static void addZeroPrefixedInt(QString &str, int num, int nDigits) @@ -1278,21 +1278,21 @@ static void addZeroPrefixedInt(QString &str, int num, int nDigits) } } -ReturnedValue DatePrototype::method_toISOString(CallContext *ctx) +void DatePrototype::method_toISOString(const BuiltinFunction *, Scope &scope, CallData *callData) { - DateObject *self = ctx->thisObject().as(); + DateObject *self = callData->thisObject.as(); if (!self) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); double t = self->date(); if (!std::isfinite(t)) - return ctx->engine()->throwRangeError(ctx->thisObject()); + RETURN_RESULT(scope.engine->throwRangeError(callData->thisObject)); QString result; int year = (int)YearFromTime(t); if (year < 0 || year > 9999) { if (qAbs(year) >= 1000000) - return ctx->d()->engine->newString(QStringLiteral("Invalid Date"))->asReturnedValue(); + RETURN_RESULT(scope.engine->newString(QStringLiteral("Invalid Date"))); result += year < 0 ? QLatin1Char('-') : QLatin1Char('+'); year = qAbs(year); addZeroPrefixedInt(result, year, 6); @@ -1313,32 +1313,29 @@ ReturnedValue DatePrototype::method_toISOString(CallContext *ctx) addZeroPrefixedInt(result, msFromTime(t), 3); result += QLatin1Char('Z'); - return ctx->d()->engine->newString(result)->asReturnedValue(); + scope.result = scope.engine->newString(result); } -ReturnedValue DatePrototype::method_toJSON(CallContext *ctx) +void DatePrototype::method_toJSON(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedObject O(scope, ctx->thisObject().toObject(scope.engine)); - if (scope.hasException()) - return Encode::undefined(); + ScopedObject O(scope, callData->thisObject.toObject(scope.engine)); + CHECK_EXCEPTION(); ScopedValue tv(scope, RuntimeHelpers::toPrimitive(O, NUMBER_HINT)); if (tv->isNumber() && !std::isfinite(tv->toNumber())) - return Encode::null(); + RETURN_RESULT(Encode::null()); - ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toISOString"))); + ScopedString s(scope, scope.engine->newString(QStringLiteral("toISOString"))); ScopedValue v(scope, O->get(s)); FunctionObject *toIso = v->as(); if (!toIso) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - ScopedCallData callData(scope); - callData->thisObject = ctx->thisObject(); - toIso->call(scope, callData); - return scope.result.asReturnedValue(); + ScopedCallData cData(scope); + cData->thisObject = callData->thisObject; + toIso->call(scope, cData); } void DatePrototype::timezoneUpdated() diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h index 835f6adbe0..a56d17f9b1 100644 --- a/src/qml/jsruntime/qv4dateobject_p.h +++ b/src/qml/jsruntime/qv4dateobject_p.h @@ -116,57 +116,57 @@ struct DatePrototype: DateObject { void init(ExecutionEngine *engine, Object *ctor); - static double getThisDate(ExecutionContext *ctx); - - static ReturnedValue method_parse(CallContext *ctx); - static ReturnedValue method_UTC(CallContext *ctx); - static ReturnedValue method_now(CallContext *ctx); - - static ReturnedValue method_toString(CallContext *ctx); - static ReturnedValue method_toDateString(CallContext *ctx); - static ReturnedValue method_toTimeString(CallContext *ctx); - static ReturnedValue method_toLocaleString(CallContext *ctx); - static ReturnedValue method_toLocaleDateString(CallContext *ctx); - static ReturnedValue method_toLocaleTimeString(CallContext *ctx); - static ReturnedValue method_valueOf(CallContext *ctx); - static ReturnedValue method_getTime(CallContext *ctx); - static ReturnedValue method_getYear(CallContext *ctx); - static ReturnedValue method_getFullYear(CallContext *ctx); - static ReturnedValue method_getUTCFullYear(CallContext *ctx); - static ReturnedValue method_getMonth(CallContext *ctx); - static ReturnedValue method_getUTCMonth(CallContext *ctx); - static ReturnedValue method_getDate(CallContext *ctx); - static ReturnedValue method_getUTCDate(CallContext *ctx); - static ReturnedValue method_getDay(CallContext *ctx); - static ReturnedValue method_getUTCDay(CallContext *ctx); - static ReturnedValue method_getHours(CallContext *ctx); - static ReturnedValue method_getUTCHours(CallContext *ctx); - static ReturnedValue method_getMinutes(CallContext *ctx); - static ReturnedValue method_getUTCMinutes(CallContext *ctx); - static ReturnedValue method_getSeconds(CallContext *ctx); - static ReturnedValue method_getUTCSeconds(CallContext *ctx); - static ReturnedValue method_getMilliseconds(CallContext *ctx); - static ReturnedValue method_getUTCMilliseconds(CallContext *ctx); - static ReturnedValue method_getTimezoneOffset(CallContext *ctx); - static ReturnedValue method_setTime(CallContext *ctx); - static ReturnedValue method_setMilliseconds(CallContext *ctx); - static ReturnedValue method_setUTCMilliseconds(CallContext *ctx); - static ReturnedValue method_setSeconds(CallContext *ctx); - static ReturnedValue method_setUTCSeconds(CallContext *ctx); - static ReturnedValue method_setMinutes(CallContext *ctx); - static ReturnedValue method_setUTCMinutes(CallContext *ctx); - static ReturnedValue method_setHours(CallContext *ctx); - static ReturnedValue method_setUTCHours(CallContext *ctx); - static ReturnedValue method_setDate(CallContext *ctx); - static ReturnedValue method_setUTCDate(CallContext *ctx); - static ReturnedValue method_setMonth(CallContext *ctx); - static ReturnedValue method_setUTCMonth(CallContext *ctx); - static ReturnedValue method_setYear(CallContext *ctx); - static ReturnedValue method_setFullYear(CallContext *ctx); - static ReturnedValue method_setUTCFullYear(CallContext *ctx); - static ReturnedValue method_toUTCString(CallContext *ctx); - static ReturnedValue method_toISOString(CallContext *ctx); - static ReturnedValue method_toJSON(CallContext *ctx); + static double getThisDate(Scope &scope, CallData *callData); + + static void method_parse(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_UTC(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_now(const BuiltinFunction *, Scope &scope, CallData *callData); + + static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toDateString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toTimeString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toLocaleDateString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toLocaleTimeString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getTime(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getYear(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getFullYear(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getUTCFullYear(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getMonth(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getUTCMonth(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getDate(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getUTCDate(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getDay(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getUTCDay(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getHours(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getUTCHours(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getMinutes(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getUTCMinutes(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getSeconds(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getUTCSeconds(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getUTCMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_getTimezoneOffset(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_setTime(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_setMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_setUTCMilliseconds(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_setSeconds(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_setUTCSeconds(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_setMinutes(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_setUTCMinutes(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_setHours(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_setUTCHours(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_setDate(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_setUTCDate(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_setMonth(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_setUTCMonth(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_setYear(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_setFullYear(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_setUTCFullYear(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toUTCString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toISOString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toJSON(const BuiltinFunction *, Scope &scope, CallData *callData); static void timezoneUpdated(); }; diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp index 3a6b9da763..09644c161d 100644 --- a/src/qml/jsruntime/qv4numberobject.cpp +++ b/src/qml/jsruntime/qv4numberobject.cpp @@ -120,61 +120,71 @@ QT_WARNING_POP defineDefaultProperty(QStringLiteral("toPrecision"), method_toPrecision); } -inline ReturnedValue thisNumberValue(ExecutionContext *ctx) +inline ReturnedValue thisNumberValue(Scope &scope, CallData *callData) { - if (ctx->thisObject().isNumber()) - return ctx->thisObject().asReturnedValue(); - NumberObject *n = ctx->thisObject().as(); - if (!n) - return ctx->engine()->throwTypeError(); + if (callData->thisObject.isNumber()) + return callData->thisObject.asReturnedValue(); + NumberObject *n = callData->thisObject.as(); + if (!n) { + scope.engine->throwTypeError(); + return Encode::undefined(); + } return Encode(n->value()); } -inline double thisNumber(ExecutionContext *ctx) +inline double thisNumber(Scope &scope, CallData *callData) { - if (ctx->thisObject().isNumber()) - return ctx->thisObject().asDouble(); - NumberObject *n = ctx->thisObject().as(); - if (!n) - return ctx->engine()->throwTypeError(); + if (callData->thisObject.isNumber()) + return callData->thisObject.asDouble(); + NumberObject *n = callData->thisObject.as(); + if (!n) { + scope.engine->throwTypeError(); + return 0; + } return n->value(); } -ReturnedValue NumberPrototype::method_isFinite(CallContext *ctx) +void NumberPrototype::method_isFinite(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (!ctx->argc()) - return Encode(false); + if (!callData->argc) { + scope.result = Encode(false); + return; + } - double v = ctx->args()[0].toNumber(); - return Encode(!std::isnan(v) && !qt_is_inf(v)); + double v = callData->args[0].toNumber(); + scope.result = Encode(!std::isnan(v) && !qt_is_inf(v)); } -ReturnedValue NumberPrototype::method_isNaN(CallContext *ctx) +void NumberPrototype::method_isNaN(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (!ctx->argc()) - return Encode(false); + if (!callData->argc) { + scope.result = Encode(false); + return; + } - double v = ctx->args()[0].toNumber(); - return Encode(std::isnan(v)); + double v = callData->args[0].toNumber(); + scope.result = Encode(std::isnan(v)); } -ReturnedValue NumberPrototype::method_toString(CallContext *ctx) +void NumberPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - double num = thisNumber(ctx); - if (scope.engine->hasException) - return Encode::undefined(); + double num = thisNumber(scope, callData); + CHECK_EXCEPTION(); - if (ctx->argc() && !ctx->args()[0].isUndefined()) { - int radix = ctx->args()[0].toInt32(); - if (radix < 2 || radix > 36) - return ctx->engine()->throwError(QStringLiteral("Number.prototype.toString: %0 is not a valid radix") + if (callData->argc && !callData->args[0].isUndefined()) { + int radix = callData->args[0].toInt32(); + if (radix < 2 || radix > 36) { + scope.result = scope.engine->throwError(QStringLiteral("Number.prototype.toString: %0 is not a valid radix") .arg(radix)); + return; + } if (std::isnan(num)) { - return scope.engine->newString(QStringLiteral("NaN"))->asReturnedValue(); + scope.result = scope.engine->newString(QStringLiteral("NaN")); + return; } else if (qt_is_inf(num)) { - return scope.engine->newString(QLatin1String(num < 0 ? "-Infinity" : "Infinity"))->asReturnedValue(); + scope.result = scope.engine->newString(QLatin1String(num < 0 ? "-Infinity" : "Infinity")); + return; } if (radix != 10) { @@ -204,45 +214,43 @@ ReturnedValue NumberPrototype::method_toString(CallContext *ctx) } if (negative) str.prepend(QLatin1Char('-')); - return scope.engine->newString(str)->asReturnedValue(); + scope.result = scope.engine->newString(str); + return; } } - return Primitive::fromDouble(num).toString(scope.engine)->asReturnedValue(); + scope.result = Primitive::fromDouble(num).toString(scope.engine); } -ReturnedValue NumberPrototype::method_toLocaleString(CallContext *ctx) +void NumberPrototype::method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedValue v(scope, thisNumberValue(ctx)); - ScopedString str(scope, v->toString(scope.engine)); - if (scope.engine->hasException) - return Encode::undefined(); - return str.asReturnedValue(); + ScopedValue v(scope, thisNumberValue(scope, callData)); + scope.result = v->toString(scope.engine); + CHECK_EXCEPTION(); } -ReturnedValue NumberPrototype::method_valueOf(CallContext *ctx) +void NumberPrototype::method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData) { - return thisNumberValue(ctx); + scope.result = thisNumberValue(scope, callData); } -ReturnedValue NumberPrototype::method_toFixed(CallContext *ctx) +void NumberPrototype::method_toFixed(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - double v = thisNumber(ctx); - if (scope.engine->hasException) - return Encode::undefined(); + double v = thisNumber(scope, callData); + CHECK_EXCEPTION(); double fdigits = 0; - if (ctx->argc() > 0) - fdigits = ctx->args()[0].toInteger(); + if (callData->argc > 0) + fdigits = callData->args[0].toInteger(); if (std::isnan(fdigits)) fdigits = 0; - if (fdigits < 0 || fdigits > 20) - return ctx->engine()->throwRangeError(ctx->thisObject()); + if (fdigits < 0 || fdigits > 20) { + scope.result = scope.engine->throwRangeError(callData->thisObject); + return; + } QString str; if (std::isnan(v)) @@ -251,48 +259,50 @@ ReturnedValue NumberPrototype::method_toFixed(CallContext *ctx) str = QString::fromLatin1(v < 0 ? "-Infinity" : "Infinity"); else if (v < 1.e21) str = NumberLocale::instance()->toString(v, 'f', int(fdigits)); - else - return RuntimeHelpers::stringFromNumber(ctx->engine(), v)->asReturnedValue(); - return scope.engine->newString(str)->asReturnedValue(); + else { + scope.result = RuntimeHelpers::stringFromNumber(scope.engine, v); + return; + } + scope.result = scope.engine->newString(str); } -ReturnedValue NumberPrototype::method_toExponential(CallContext *ctx) +void NumberPrototype::method_toExponential(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - double d = thisNumber(ctx); - if (scope.engine->hasException) - return Encode::undefined(); + double d = thisNumber(scope, callData); + CHECK_EXCEPTION(); int fdigits = NumberLocale::instance()->defaultDoublePrecision; - if (ctx->argc() && !ctx->args()[0].isUndefined()) { - fdigits = ctx->args()[0].toInt32(); + if (callData->argc && !callData->args[0].isUndefined()) { + fdigits = callData->args[0].toInt32(); if (fdigits < 0 || fdigits > 20) { ScopedString error(scope, scope.engine->newString(QStringLiteral("Number.prototype.toExponential: fractionDigits out of range"))); - return ctx->engine()->throwRangeError(error); + scope.result = scope.engine->throwRangeError(error); + return; } } QString result = NumberLocale::instance()->toString(d, 'e', fdigits); - return scope.engine->newString(result)->asReturnedValue(); + scope.result = scope.engine->newString(result); } -ReturnedValue NumberPrototype::method_toPrecision(CallContext *ctx) +void NumberPrototype::method_toPrecision(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedValue v(scope, thisNumberValue(ctx)); - if (scope.engine->hasException) - return Encode::undefined(); + ScopedValue v(scope, thisNumberValue(scope, callData)); + CHECK_EXCEPTION(); - if (!ctx->argc() || ctx->args()[0].isUndefined()) - return Encode(v->toString(scope.engine)); + if (!callData->argc || callData->args[0].isUndefined()) { + scope.result = v->toString(scope.engine); + return; + } - int precision = ctx->args()[0].toInt32(); + int precision = callData->args[0].toInt32(); if (precision < 1 || precision > 21) { ScopedString error(scope, scope.engine->newString(QStringLiteral("Number.prototype.toPrecision: precision out of range"))); - return ctx->engine()->throwRangeError(error); + scope.result = scope.engine->throwRangeError(error); + return; } QString result = NumberLocale::instance()->toString(v->asDouble(), 'g', precision); - return scope.engine->newString(result)->asReturnedValue(); + scope.result = scope.engine->newString(result); } diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h index 6022b3a029..364b866a16 100644 --- a/src/qml/jsruntime/qv4numberobject_p.h +++ b/src/qml/jsruntime/qv4numberobject_p.h @@ -87,14 +87,14 @@ struct NumberPrototype: NumberObject { void init(ExecutionEngine *engine, Object *ctor); - static ReturnedValue method_isFinite(CallContext *ctx); - static ReturnedValue method_isNaN(CallContext *ctx); - static ReturnedValue method_toString(CallContext *ctx); - static ReturnedValue method_toLocaleString(CallContext *ctx); - static ReturnedValue method_valueOf(CallContext *ctx); - static ReturnedValue method_toFixed(CallContext *ctx); - static ReturnedValue method_toExponential(CallContext *ctx); - static ReturnedValue method_toPrecision(CallContext *ctx); + static void method_isFinite(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_isNaN(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toFixed(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toExponential(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toPrecision(const BuiltinFunction *, Scope &scope, CallData *callData); }; diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 6fbf1c3c85..3c6a24e035 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -214,10 +214,9 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("trim"), method_trim); } -static QString getThisString(ExecutionContext *ctx) +static QString getThisString(Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedValue t(scope, ctx->thisObject()); + ScopedValue t(scope, callData->thisObject); if (String *s = t->stringValue()) return s->toQString(); if (StringObject *thisString = t->as()) @@ -229,158 +228,146 @@ static QString getThisString(ExecutionContext *ctx) return t->toQString(); } -ReturnedValue StringPrototype::method_toString(CallContext *context) +void StringPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (context->thisObject().isString()) - return context->thisObject().asReturnedValue(); + if (callData->thisObject.isString()) + RETURN_RESULT(callData->thisObject); - StringObject *o = context->thisObject().as(); + StringObject *o = callData->thisObject.as(); if (!o) - return context->engine()->throwTypeError(); - return Encode(o->d()->string); + THROW_TYPE_ERROR(); + scope.result = o->d()->string; } -ReturnedValue StringPrototype::method_charAt(CallContext *context) +void StringPrototype::method_charAt(const BuiltinFunction *, Scope &scope, CallData *callData) { - const QString str = getThisString(context); - if (context->d()->engine->hasException) - return Encode::undefined(); + const QString str = getThisString(scope, callData); + CHECK_EXCEPTION(); int pos = 0; - if (context->argc() > 0) - pos = (int) context->args()[0].toInteger(); + if (callData->argc > 0) + pos = (int) callData->args[0].toInteger(); QString result; if (pos >= 0 && pos < str.length()) result += str.at(pos); - return context->d()->engine->newString(result)->asReturnedValue(); + scope.result = scope.engine->newString(result); } -ReturnedValue StringPrototype::method_charCodeAt(CallContext *context) +void StringPrototype::method_charCodeAt(const BuiltinFunction *, Scope &scope, CallData *callData) { - const QString str = getThisString(context); - if (context->d()->engine->hasException) - return Encode::undefined(); + const QString str = getThisString(scope, callData); + CHECK_EXCEPTION(); int pos = 0; - if (context->argc() > 0) - pos = (int) context->args()[0].toInteger(); + if (callData->argc > 0) + pos = (int) callData->args[0].toInteger(); if (pos >= 0 && pos < str.length()) - return Encode(str.at(pos).unicode()); + RETURN_RESULT(Encode(str.at(pos).unicode())); - return Encode(qt_qnan()); + scope.result = Encode(qt_qnan()); } -ReturnedValue StringPrototype::method_concat(CallContext *context) +void StringPrototype::method_concat(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(context); - - QString value = getThisString(context); - if (scope.engine->hasException) - return Encode::undefined(); + QString value = getThisString(scope, callData); + CHECK_EXCEPTION(); ScopedString s(scope); - for (int i = 0; i < context->argc(); ++i) { - s = context->args()[i].toString(scope.engine); - if (scope.hasException()) - return Encode::undefined(); + for (int i = 0; i < callData->argc; ++i) { + s = callData->args[i].toString(scope.engine); + CHECK_EXCEPTION(); + Q_ASSERT(s->isString()); value += s->toQString(); } - return context->d()->engine->newString(value)->asReturnedValue(); + scope.result = scope.engine->newString(value); } -ReturnedValue StringPrototype::method_endsWith(CallContext *context) +void StringPrototype::method_endsWith(const BuiltinFunction *, Scope &scope, CallData *callData) { - QString value = getThisString(context); - if (context->d()->engine->hasException) - return Encode::undefined(); + QString value = getThisString(scope, callData); + CHECK_EXCEPTION(); QString searchString; - if (context->argc()) { - if (context->args()[0].as()) - return context->engine()->throwTypeError(); - searchString = context->args()[0].toQString(); + if (callData->argc) { + if (callData->args[0].as()) + THROW_TYPE_ERROR(); + searchString = callData->args[0].toQString(); } int pos = value.length(); - if (context->argc() > 1) - pos = (int) context->args()[1].toInteger(); + if (callData->argc > 1) + pos = (int) callData->args[1].toInteger(); if (pos == value.length()) - return Encode(value.endsWith(searchString)); + RETURN_RESULT(Encode(value.endsWith(searchString))); QStringRef stringToSearch = value.leftRef(pos); - return Encode(stringToSearch.endsWith(searchString)); + scope.result = Encode(stringToSearch.endsWith(searchString)); } -ReturnedValue StringPrototype::method_indexOf(CallContext *context) +void StringPrototype::method_indexOf(const BuiltinFunction *, Scope &scope, CallData *callData) { - QString value = getThisString(context); - if (context->d()->engine->hasException) - return Encode::undefined(); + QString value = getThisString(scope, callData); + CHECK_EXCEPTION(); QString searchString; - if (context->argc()) - searchString = context->args()[0].toQString(); + if (callData->argc) + searchString = callData->args[0].toQString(); int pos = 0; - if (context->argc() > 1) - pos = (int) context->args()[1].toInteger(); + if (callData->argc > 1) + pos = (int) callData->args[1].toInteger(); int index = -1; if (! value.isEmpty()) index = value.indexOf(searchString, qMin(qMax(pos, 0), value.length())); - return Encode(index); + scope.result = Encode(index); } -ReturnedValue StringPrototype::method_includes(CallContext *context) +void StringPrototype::method_includes(const BuiltinFunction *, Scope &scope, CallData *callData) { - QString value = getThisString(context); - if (context->d()->engine->hasException) - return Encode::undefined(); + QString value = getThisString(scope, callData); + CHECK_EXCEPTION(); QString searchString; - if (context->argc()) { - if (context->args()[0].as()) - return context->engine()->throwTypeError(); - searchString = context->args()[0].toQString(); + if (callData->argc) { + if (callData->args[0].as()) + THROW_TYPE_ERROR(); + searchString = callData->args[0].toQString(); } int pos = 0; - if (context->argc() > 1) { - Scope scope(context); - ScopedValue posArg(scope, context->argument(1)); + if (callData->argc > 1) { + ScopedValue posArg(scope, callData->argument(1)); pos = (int) posArg->toInteger(); if (!posArg->isInteger() && posArg->isNumber() && qIsInf(posArg->toNumber())) pos = value.length(); } if (pos == 0) - return Encode(value.contains(searchString)); + RETURN_RESULT(Encode(value.contains(searchString))); QStringRef stringToSearch = value.midRef(pos); - return Encode(stringToSearch.contains(searchString)); + scope.result = Encode(stringToSearch.contains(searchString)); } -ReturnedValue StringPrototype::method_lastIndexOf(CallContext *context) +void StringPrototype::method_lastIndexOf(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(context); - - const QString value = getThisString(context); - if (scope.engine->hasException) - return Encode::undefined(); + const QString value = getThisString(scope, callData); + CHECK_EXCEPTION(); QString searchString; - if (context->argc()) - searchString = context->args()[0].toQString(); + if (callData->argc) + searchString = callData->args[0].toQString(); - ScopedValue posArg(scope, context->argument(1)); + ScopedValue posArg(scope, callData->argument(1)); double position = RuntimeHelpers::toNumber(posArg); if (std::isnan(position)) position = +qInf(); @@ -391,43 +378,40 @@ ReturnedValue StringPrototype::method_lastIndexOf(CallContext *context) if (!searchString.isEmpty() && pos == value.length()) --pos; if (searchString.isNull() && pos == 0) - return Encode(-1); + RETURN_RESULT(Encode(-1)); int index = value.lastIndexOf(searchString, pos); - return Encode(index); + scope.result = Encode(index); } -ReturnedValue StringPrototype::method_localeCompare(CallContext *context) +void StringPrototype::method_localeCompare(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(context); - const QString value = getThisString(context); - if (scope.engine->hasException) - return Encode::undefined(); + const QString value = getThisString(scope, callData); + CHECK_EXCEPTION(); - ScopedValue v(scope, context->argument(0)); + ScopedValue v(scope, callData->argument(0)); const QString that = v->toQString(); - return Encode(QString::localeAwareCompare(value, that)); + scope.result = Encode(QString::localeAwareCompare(value, that)); } -ReturnedValue StringPrototype::method_match(CallContext *context) +void StringPrototype::method_match(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (context->thisObject().isUndefined() || context->thisObject().isNull()) - return context->engine()->throwTypeError(); + if (callData->thisObject.isUndefined() || callData->thisObject.isNull()) + THROW_TYPE_ERROR(); - Scope scope(context); - ScopedString s(scope, context->thisObject().toString(scope.engine)); + ScopedString s(scope, callData->thisObject.toString(scope.engine)); - ScopedValue regexp(scope, context->argument(0)); + ScopedValue regexp(scope, callData->argument(0)); Scoped rx(scope, regexp); if (!rx) { ScopedCallData callData(scope, 1); callData->args[0] = regexp; - context->d()->engine->regExpCtor()->construct(scope, callData); + scope.engine->regExpCtor()->construct(scope, callData); rx = scope.result.asReturnedValue(); } if (!rx) // ### CHECK - return context->engine()->throwTypeError(); + THROW_TYPE_ERROR(); bool global = rx->global(); @@ -435,24 +419,24 @@ ReturnedValue StringPrototype::method_match(CallContext *context) ScopedString execString(scope, scope.engine->newString(QStringLiteral("exec"))); ScopedFunctionObject exec(scope, scope.engine->regExpPrototype()->get(execString)); - ScopedCallData callData(scope, 1); - callData->thisObject = rx; - callData->args[0] = s; + ScopedCallData cData(scope, 1); + cData->thisObject = rx; + cData->args[0] = s; if (!global) { - exec->call(scope, callData); - return scope.result.asReturnedValue(); + exec->call(scope, cData); + return; } - ScopedString lastIndex(scope, context->d()->engine->newString(QStringLiteral("lastIndex"))); + ScopedString lastIndex(scope, scope.engine->newString(QStringLiteral("lastIndex"))); rx->put(lastIndex, ScopedValue(scope, Primitive::fromInt32(0))); - ScopedArrayObject a(scope, context->d()->engine->newArrayObject()); + ScopedArrayObject a(scope, scope.engine->newArrayObject()); double previousLastIndex = 0; uint n = 0; ScopedValue matchStr(scope); ScopedValue index(scope); while (1) { - exec->call(scope, callData); + exec->call(scope, cData); if (scope.result.isNull()) break; assert(scope.result.isObject()); @@ -469,10 +453,9 @@ ReturnedValue StringPrototype::method_match(CallContext *context) ++n; } if (!n) - return Encode::null(); - - return a.asReturnedValue(); - + scope.result = Encode::null(); + else + scope.result = a; } static void appendReplacementString(QString *result, const QString &input, const QString& replaceValue, uint* matchOffsets, int captureCount) @@ -521,14 +504,13 @@ static void appendReplacementString(QString *result, const QString &input, const } } -ReturnedValue StringPrototype::method_replace(CallContext *ctx) +void StringPrototype::method_replace(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); QString string; - if (StringObject *thisString = ctx->thisObject().as()) + if (StringObject *thisString = callData->thisObject.as()) string = thisString->d()->string->toQString(); else - string = ctx->thisObject().toQString(); + string = callData->thisObject.toQString(); int numCaptures = 0; int numStringMatches = 0; @@ -537,7 +519,7 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) uint _matchOffsets[64]; uint *matchOffsets = _matchOffsets; - ScopedValue searchValue(scope, ctx->argument(0)); + ScopedValue searchValue(scope, callData->argument(0)); Scoped regExp(scope, searchValue); if (regExp) { uint offset = 0; @@ -580,7 +562,7 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) } QString result; - ScopedValue replaceValue(scope, ctx->argument(1)); + ScopedValue replaceValue(scope, callData->argument(1)); ScopedFunctionObject searchCallback(scope, replaceValue); if (!!searchCallback) { result.reserve(string.length() + 10*numStringMatches); @@ -595,14 +577,14 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) uint end = matchOffsets[idx + 1]; entry = Primitive::undefinedValue(); if (start != JSC::Yarr::offsetNoMatch && end != JSC::Yarr::offsetNoMatch) - entry = ctx->d()->engine->newString(string.mid(start, end - start)); + entry = scope.engine->newString(string.mid(start, end - start)); callData->args[k] = entry; } uint matchStart = matchOffsets[i * numCaptures * 2]; Q_ASSERT(matchStart >= static_cast(lastEnd)); uint matchEnd = matchOffsets[i * numCaptures * 2 + 1]; callData->args[numCaptures] = Primitive::fromUInt32(matchStart); - callData->args[numCaptures + 1] = ctx->d()->engine->newString(string); + callData->args[numCaptures + 1] = scope.engine->newString(string); searchCallback->call(scope, callData); result += string.midRef(lastEnd, matchStart - lastEnd); @@ -632,23 +614,22 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) if (matchOffsets != _matchOffsets) free(matchOffsets); - return ctx->d()->engine->newString(result)->asReturnedValue(); + scope.result = scope.engine->newString(result); } -ReturnedValue StringPrototype::method_search(CallContext *ctx) +void StringPrototype::method_search(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - QString string = getThisString(ctx); - scope.result = ctx->argument(0); - if (scope.engine->hasException) - return Encode::undefined(); + QString string = getThisString(scope, callData); + scope.result = callData->argument(0); + CHECK_EXCEPTION(); + Scoped regExp(scope, scope.result.as()); if (!regExp) { ScopedCallData callData(scope, 1); callData->args[0] = scope.result; - ctx->d()->engine->regExpCtor()->construct(scope, callData); - if (scope.engine->hasException) - return Encode::undefined(); + scope.engine->regExpCtor()->construct(scope, callData); + CHECK_EXCEPTION(); + regExp = scope.result.as(); Q_ASSERT(regExp); } @@ -656,21 +637,21 @@ ReturnedValue StringPrototype::method_search(CallContext *ctx) uint* matchOffsets = (uint*)alloca(regExp->value()->captureCount() * 2 * sizeof(uint)); uint result = re->match(string, /*offset*/0, matchOffsets); if (result == JSC::Yarr::offsetNoMatch) - return Encode(-1); - return Encode(result); + scope.result = Encode(-1); + else + scope.result = Encode(result); } -ReturnedValue StringPrototype::method_slice(CallContext *ctx) +void StringPrototype::method_slice(const BuiltinFunction *, Scope &scope, CallData *callData) { - const QString text = getThisString(ctx); - if (ctx->d()->engine->hasException) - return Encode::undefined(); + const QString text = getThisString(scope, callData); + CHECK_EXCEPTION(); const double length = text.length(); - double start = ctx->argc() ? ctx->args()[0].toInteger() : 0; - double end = (ctx->argc() < 2 || ctx->args()[1].isUndefined()) - ? length : ctx->args()[1].toInteger(); + double start = callData->argc ? callData->args[0].toInteger() : 0; + double end = (callData->argc < 2 || callData->args[1].isUndefined()) + ? length : callData->args[1].toInteger(); if (start < 0) start = qMax(length + start, 0.); @@ -686,40 +667,38 @@ ReturnedValue StringPrototype::method_slice(CallContext *ctx) const int intEnd = int(end); int count = qMax(0, intEnd - intStart); - return ctx->d()->engine->newString(text.mid(intStart, count))->asReturnedValue(); + scope.result = scope.engine->newString(text.mid(intStart, count)); } -ReturnedValue StringPrototype::method_split(CallContext *ctx) +void StringPrototype::method_split(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - QString text = getThisString(ctx); - if (scope.engine->hasException) - return Encode::undefined(); + QString text = getThisString(scope, callData); + CHECK_EXCEPTION(); - ScopedValue separatorValue(scope, ctx->argument(0)); - ScopedValue limitValue(scope, ctx->argument(1)); + ScopedValue separatorValue(scope, callData->argument(0)); + ScopedValue limitValue(scope, callData->argument(1)); - ScopedArrayObject array(scope, ctx->d()->engine->newArrayObject()); + ScopedArrayObject array(scope, scope.engine->newArrayObject()); if (separatorValue->isUndefined()) { if (limitValue->isUndefined()) { - ScopedString s(scope, ctx->d()->engine->newString(text)); + ScopedString s(scope, scope.engine->newString(text)); array->push_back(s); - return array.asReturnedValue(); + RETURN_RESULT(array); } - return ctx->d()->engine->newString(text.left(limitValue->toInteger()))->asReturnedValue(); + RETURN_RESULT(scope.engine->newString(text.left(limitValue->toInteger()))); } uint limit = limitValue->isUndefined() ? UINT_MAX : limitValue->toUInt32(); if (limit == 0) - return array.asReturnedValue(); + RETURN_RESULT(array); Scoped re(scope, separatorValue); if (re) { if (re->value()->pattern->isEmpty()) { re = (RegExpObject *)0; - separatorValue = ctx->d()->engine->newString(); + separatorValue = scope.engine->newString(); } } @@ -733,7 +712,7 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx) if (result == JSC::Yarr::offsetNoMatch) break; - array->push_back((s = ctx->d()->engine->newString(text.mid(offset, matchOffsets[0] - offset)))); + array->push_back((s = scope.engine->newString(text.mid(offset, matchOffsets[0] - offset)))); offset = qMax(offset + 1, matchOffsets[1]); if (array->getLength() >= limit) @@ -742,72 +721,70 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx) for (int i = 1; i < re->value()->captureCount(); ++i) { uint start = matchOffsets[i * 2]; uint end = matchOffsets[i * 2 + 1]; - array->push_back((s = ctx->d()->engine->newString(text.mid(start, end - start)))); + array->push_back((s = scope.engine->newString(text.mid(start, end - start)))); if (array->getLength() >= limit) break; } } if (array->getLength() < limit) - array->push_back((s = ctx->d()->engine->newString(text.mid(offset)))); + array->push_back((s = scope.engine->newString(text.mid(offset)))); } else { QString separator = separatorValue->toQString(); if (separator.isEmpty()) { for (uint i = 0; i < qMin(limit, uint(text.length())); ++i) - array->push_back((s = ctx->d()->engine->newString(text.mid(i, 1)))); - return array.asReturnedValue(); + array->push_back((s = scope.engine->newString(text.mid(i, 1)))); + RETURN_RESULT(array); } int start = 0; int end; while ((end = text.indexOf(separator, start)) != -1) { - array->push_back((s = ctx->d()->engine->newString(text.mid(start, end - start)))); + array->push_back((s = scope.engine->newString(text.mid(start, end - start)))); start = end + separator.size(); if (array->getLength() >= limit) break; } if (array->getLength() < limit && start != -1) - array->push_back((s = ctx->d()->engine->newString(text.mid(start)))); + array->push_back((s = scope.engine->newString(text.mid(start)))); } - return array.asReturnedValue(); + RETURN_RESULT(array); } -ReturnedValue StringPrototype::method_startsWith(CallContext *context) +void StringPrototype::method_startsWith(const BuiltinFunction *, Scope &scope, CallData *callData) { - QString value = getThisString(context); - if (context->d()->engine->hasException) - return Encode::undefined(); + QString value = getThisString(scope, callData); + CHECK_EXCEPTION(); QString searchString; - if (context->argc()) { - if (context->args()[0].as()) - return context->engine()->throwTypeError(); - searchString = context->args()[0].toQString(); + if (callData->argc) { + if (callData->args[0].as()) + THROW_TYPE_ERROR(); + searchString = callData->args[0].toQString(); } int pos = 0; - if (context->argc() > 1) - pos = (int) context->args()[1].toInteger(); + if (callData->argc > 1) + pos = (int) callData->args[1].toInteger(); if (pos == 0) - return Encode(value.startsWith(searchString)); + RETURN_RESULT(Encode(value.startsWith(searchString))); QStringRef stringToSearch = value.midRef(pos); - return Encode(stringToSearch.startsWith(searchString)); + RETURN_RESULT(Encode(stringToSearch.startsWith(searchString))); } -ReturnedValue StringPrototype::method_substr(CallContext *context) +void StringPrototype::method_substr(const BuiltinFunction *, Scope &scope, CallData *callData) { - const QString value = getThisString(context); - if (context->d()->engine->hasException) - return Encode::undefined(); + const QString value = getThisString(scope, callData); + CHECK_EXCEPTION(); double start = 0; - if (context->argc() > 0) - start = context->args()[0].toInteger(); + if (callData->argc > 0) + start = callData->args[0].toInteger(); double length = +qInf(); - if (context->argc() > 1) - length = context->args()[1].toInteger(); + if (callData->argc > 1) + length = callData->args[1].toInteger(); double count = value.length(); if (start < 0) @@ -817,24 +794,23 @@ ReturnedValue StringPrototype::method_substr(CallContext *context) qint32 x = Primitive::toInt32(start); qint32 y = Primitive::toInt32(length); - return context->d()->engine->newString(value.mid(x, y))->asReturnedValue(); + scope.result = scope.engine->newString(value.mid(x, y)); } -ReturnedValue StringPrototype::method_substring(CallContext *context) +void StringPrototype::method_substring(const BuiltinFunction *, Scope &scope, CallData *callData) { - QString value = getThisString(context); - if (context->d()->engine->hasException) - return Encode::undefined(); + QString value = getThisString(scope, callData); + CHECK_EXCEPTION(); + int length = value.length(); double start = 0; double end = length; - if (context->argc() > 0) - start = context->args()[0].toInteger(); + if (callData->argc > 0) + start = callData->args[0].toInteger(); - Scope scope(context); - ScopedValue endValue(scope, context->argument(1)); + ScopedValue endValue(scope, callData->argument(1)); if (!endValue->isUndefined()) end = endValue->toInteger(); @@ -858,51 +834,50 @@ ReturnedValue StringPrototype::method_substring(CallContext *context) qint32 x = (int)start; qint32 y = (int)(end - start); - return context->d()->engine->newString(value.mid(x, y))->asReturnedValue(); + scope.result = scope.engine->newString(value.mid(x, y)); } -ReturnedValue StringPrototype::method_toLowerCase(CallContext *ctx) +void StringPrototype::method_toLowerCase(const BuiltinFunction *, Scope &scope, CallData *callData) { - QString value = getThisString(ctx); - if (ctx->d()->engine->hasException) - return Encode::undefined(); - return ctx->d()->engine->newString(value.toLower())->asReturnedValue(); + QString value = getThisString(scope, callData); + CHECK_EXCEPTION(); + + scope.result = scope.engine->newString(value.toLower()); } -ReturnedValue StringPrototype::method_toLocaleLowerCase(CallContext *ctx) +void StringPrototype::method_toLocaleLowerCase(const BuiltinFunction *b, Scope &scope, CallData *callData) { - return method_toLowerCase(ctx); + method_toLowerCase(b, scope, callData); } -ReturnedValue StringPrototype::method_toUpperCase(CallContext *ctx) +void StringPrototype::method_toUpperCase(const BuiltinFunction *, Scope &scope, CallData *callData) { - QString value = getThisString(ctx); - if (ctx->d()->engine->hasException) - return Encode::undefined(); - return ctx->d()->engine->newString(value.toUpper())->asReturnedValue(); + QString value = getThisString(scope, callData); + CHECK_EXCEPTION(); + + scope.result = scope.engine->newString(value.toUpper()); } -ReturnedValue StringPrototype::method_toLocaleUpperCase(CallContext *ctx) +void StringPrototype::method_toLocaleUpperCase(const BuiltinFunction *b, Scope &scope, CallData *callData) { - return method_toUpperCase(ctx); + return method_toUpperCase(b, scope, callData); } -ReturnedValue StringPrototype::method_fromCharCode(CallContext *context) +void StringPrototype::method_fromCharCode(const BuiltinFunction *, Scope &scope, CallData *callData) { - QString str(context->argc(), Qt::Uninitialized); + QString str(callData->argc, Qt::Uninitialized); QChar *ch = str.data(); - for (int i = 0; i < context->argc(); ++i) { - *ch = QChar(context->args()[i].toUInt16()); + for (int i = 0; i < callData->argc; ++i) { + *ch = QChar(callData->args[i].toUInt16()); ++ch; } - return context->d()->engine->newString(str)->asReturnedValue(); + scope.result = scope.engine->newString(str); } -ReturnedValue StringPrototype::method_trim(CallContext *ctx) +void StringPrototype::method_trim(const BuiltinFunction *, Scope &scope, CallData *callData) { - QString s = getThisString(ctx); - if (ctx->d()->engine->hasException) - return Encode::undefined(); + QString s = getThisString(scope, callData); + CHECK_EXCEPTION(); const QChar *chars = s.constData(); int start, end; @@ -915,5 +890,5 @@ ReturnedValue StringPrototype::method_trim(CallContext *ctx) break; } - return ctx->d()->engine->newString(QString(chars + start, end - start + 1))->asReturnedValue(); + scope.result = scope.engine->newString(QString(chars + start, end - start + 1)); } diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h index b9f9d44fe8..0ee7a6ece9 100644 --- a/src/qml/jsruntime/qv4stringobject_p.h +++ b/src/qml/jsruntime/qv4stringobject_p.h @@ -111,29 +111,29 @@ struct StringPrototype: StringObject { void init(ExecutionEngine *engine, Object *ctor); - static ReturnedValue method_toString(CallContext *context); - static ReturnedValue method_charAt(CallContext *context); - static ReturnedValue method_charCodeAt(CallContext *context); - static ReturnedValue method_concat(CallContext *context); - static ReturnedValue method_endsWith(CallContext *ctx); - static ReturnedValue method_indexOf(CallContext *context); - static ReturnedValue method_includes(CallContext *context); - static ReturnedValue method_lastIndexOf(CallContext *context); - static ReturnedValue method_localeCompare(CallContext *context); - static ReturnedValue method_match(CallContext *context); - static ReturnedValue method_replace(CallContext *ctx); - static ReturnedValue method_search(CallContext *ctx); - static ReturnedValue method_slice(CallContext *ctx); - static ReturnedValue method_split(CallContext *ctx); - static ReturnedValue method_startsWith(CallContext *ctx); - static ReturnedValue method_substr(CallContext *context); - static ReturnedValue method_substring(CallContext *context); - static ReturnedValue method_toLowerCase(CallContext *ctx); - static ReturnedValue method_toLocaleLowerCase(CallContext *ctx); - static ReturnedValue method_toUpperCase(CallContext *ctx); - static ReturnedValue method_toLocaleUpperCase(CallContext *ctx); - static ReturnedValue method_fromCharCode(CallContext *context); - static ReturnedValue method_trim(CallContext *ctx); + static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_charAt(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_charCodeAt(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_concat(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_endsWith(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_indexOf(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_includes(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_lastIndexOf(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_localeCompare(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_match(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_replace(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_search(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_slice(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_split(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_startsWith(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_substr(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_substring(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toLowerCase(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toLocaleLowerCase(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toUpperCase(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toLocaleUpperCase(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_fromCharCode(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_trim(const BuiltinFunction *, Scope &scope, CallData *callData); }; } diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index 3876e774c3..712da78807 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -56,10 +56,17 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(QQmlLocaleData); +#define THROW_ERROR(string) \ + do { \ + scope.result = scope.engine->throwError(QString::fromUtf8(string)); \ + return; \ + } while (false) + + #define GET_LOCALE_DATA_RESOURCE(OBJECT) \ QV4::Scoped r(scope, OBJECT.as()); \ if (!r) \ - V4THROW_ERROR("Not a valid Locale object") + THROW_ERROR("Not a valid Locale object") static bool isLocaleObject(const QV4::Value &val) { @@ -80,215 +87,219 @@ void QQmlDateExtension::registerExtension(QV4::ExecutionEngine *engine) engine->dateCtor()->defineDefaultProperty(QStringLiteral("timeZoneUpdated"), method_timeZoneUpdated); } -QV4::ReturnedValue QQmlDateExtension::method_toLocaleString(QV4::CallContext *ctx) +void QQmlDateExtension::method_toLocaleString(const BuiltinFunction *b, Scope &scope, CallData *callData) { - if (ctx->argc() > 2) - return QV4::DatePrototype::method_toLocaleString(ctx); - - QV4::Scope scope(ctx); + if (callData->argc > 2) { + QV4::DatePrototype::method_toLocaleString(b, scope, callData); + return; + } - QV4::DateObject *date = ctx->thisObject().as(); - if (!date) - return QV4::DatePrototype::method_toLocaleString(ctx); + QV4::DateObject *date = callData->thisObject.as(); + if (!date) { + QV4::DatePrototype::method_toLocaleString(b, scope, callData); + return; + } QDateTime dt = date->toQDateTime(); - if (ctx->argc() == 0) { + if (callData->argc == 0) { // Use QLocale for standard toLocaleString() function QLocale locale; - return ctx->d()->engine->newString(locale.toString(dt))->asReturnedValue(); + RETURN_RESULT(scope.engine->newString(locale.toString(dt))); } - if (!isLocaleObject(ctx->args()[0])) - return QV4::DatePrototype::method_toLocaleString(ctx); // Use the default Date toLocaleString() + if (!isLocaleObject(callData->args[0])) { + QV4::DatePrototype::method_toLocaleString(b, scope, callData); // Use the default Date toLocaleString() + return; + } - GET_LOCALE_DATA_RESOURCE(ctx->args()[0]); + GET_LOCALE_DATA_RESOURCE(callData->args[0]); QLocale::FormatType enumFormat = QLocale::LongFormat; QString formattedDt; - if (ctx->argc() == 2) { - if (String *s = ctx->args()[1].stringValue()) { + if (callData->argc == 2) { + if (String *s = callData->args[1].stringValue()) { QString format = s->toQString(); formattedDt = r->d()->locale->toString(dt, format); - } else if (ctx->args()[1].isNumber()) { - quint32 intFormat = ctx->args()[1].toNumber(); + } else if (callData->args[1].isNumber()) { + quint32 intFormat = callData->args[1].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); formattedDt = r->d()->locale->toString(dt, format); } else { - V4THROW_ERROR("Locale: Date.toLocaleString(): Invalid datetime format"); + THROW_ERROR("Locale: Date.toLocaleString(): Invalid datetime format"); } } else { formattedDt = r->d()->locale->toString(dt, enumFormat); } - return ctx->d()->engine->newString(formattedDt)->asReturnedValue(); + scope.result = scope.engine->newString(formattedDt); } -QV4::ReturnedValue QQmlDateExtension::method_toLocaleTimeString(QV4::CallContext *ctx) +void QQmlDateExtension::method_toLocaleTimeString(const BuiltinFunction *b, Scope &scope, CallData *callData) { - if (ctx->argc() > 2) - return QV4::DatePrototype::method_toLocaleTimeString(ctx); - - QV4::Scope scope(ctx); + if (callData->argc > 2) { + QV4::DatePrototype::method_toLocaleTimeString(b, scope, callData); + return; + } - QV4::DateObject *date = ctx->thisObject().as(); - if (!date) - return QV4::DatePrototype::method_toLocaleTimeString(ctx); + QV4::DateObject *date = callData->thisObject.as(); + if (!date) { + QV4::DatePrototype::method_toLocaleTimeString(b, scope, callData); + return; + } QDateTime dt = date->toQDateTime(); QTime time = dt.time(); - if (ctx->argc() == 0) { + if (callData->argc == 0) { // Use QLocale for standard toLocaleString() function QLocale locale; - return ctx->d()->engine->newString(locale.toString(time))->asReturnedValue(); + RETURN_RESULT(scope.engine->newString(locale.toString(time))); } - if (!isLocaleObject(ctx->args()[0])) - return QV4::DatePrototype::method_toLocaleTimeString(ctx); // Use the default Date toLocaleTimeString() + if (!isLocaleObject(callData->args[0])) + return QV4::DatePrototype::method_toLocaleTimeString(b, scope, callData); // Use the default Date toLocaleTimeString() - GET_LOCALE_DATA_RESOURCE(ctx->args()[0]); + GET_LOCALE_DATA_RESOURCE(callData->args[0]); QLocale::FormatType enumFormat = QLocale::LongFormat; QString formattedTime; - if (ctx->argc() == 2) { - if (String *s = ctx->args()[1].stringValue()) { + if (callData->argc == 2) { + if (String *s = callData->args[1].stringValue()) { QString format = s->toQString(); formattedTime = r->d()->locale->toString(time, format); - } else if (ctx->args()[1].isNumber()) { - quint32 intFormat = ctx->args()[1].toNumber(); + } else if (callData->args[1].isNumber()) { + quint32 intFormat = callData->args[1].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); formattedTime = r->d()->locale->toString(time, format); } else { - V4THROW_ERROR("Locale: Date.toLocaleTimeString(): Invalid time format"); + THROW_ERROR("Locale: Date.toLocaleTimeString(): Invalid time format"); } } else { formattedTime = r->d()->locale->toString(time, enumFormat); } - return ctx->d()->engine->newString(formattedTime)->asReturnedValue(); + scope.result = scope.engine->newString(formattedTime); } -QV4::ReturnedValue QQmlDateExtension::method_toLocaleDateString(QV4::CallContext *ctx) +void QQmlDateExtension::method_toLocaleDateString(const BuiltinFunction *b, Scope &scope, CallData *callData) { - if (ctx->argc() > 2) - return QV4::DatePrototype::method_toLocaleDateString(ctx); - - QV4::Scope scope(ctx); + if (callData->argc > 2) { + QV4::DatePrototype::method_toLocaleDateString(b, scope, callData); + return; + } - QV4::DateObject *dateObj = ctx->thisObject().as(); - if (!dateObj) - return QV4::DatePrototype::method_toLocaleDateString(ctx); + QV4::DateObject *dateObj = callData->thisObject.as(); + if (!dateObj) { + QV4::DatePrototype::method_toLocaleDateString(b, scope, callData); + return; + } QDateTime dt = dateObj->toQDateTime(); QDate date = dt.date(); - if (ctx->argc() == 0) { + if (callData->argc == 0) { // Use QLocale for standard toLocaleString() function QLocale locale; - return ctx->d()->engine->newString(locale.toString(date))->asReturnedValue(); + RETURN_RESULT(scope.engine->newString(locale.toString(date))); } - if (!isLocaleObject(ctx->args()[0])) - return QV4::DatePrototype::method_toLocaleDateString(ctx); // Use the default Date toLocaleDateString() + if (!isLocaleObject(callData->args[0])) + return QV4::DatePrototype::method_toLocaleDateString(b, scope, callData); // Use the default Date toLocaleDateString() - GET_LOCALE_DATA_RESOURCE(ctx->args()[0]); + GET_LOCALE_DATA_RESOURCE(callData->args[0]); QLocale::FormatType enumFormat = QLocale::LongFormat; QString formattedDate; - if (ctx->argc() == 2) { - if (String *s = ctx->args()[1].stringValue()) { + if (callData->argc == 2) { + if (String *s = callData->args[1].stringValue()) { QString format = s->toQString(); formattedDate = r->d()->locale->toString(date, format); - } else if (ctx->args()[1].isNumber()) { - quint32 intFormat = ctx->args()[1].toNumber(); + } else if (callData->args[1].isNumber()) { + quint32 intFormat = callData->args[1].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); formattedDate = r->d()->locale->toString(date, format); } else { - V4THROW_ERROR("Locale: Date.loLocaleDateString(): Invalid date format"); + THROW_ERROR("Locale: Date.loLocaleDateString(): Invalid date format"); } } else { formattedDate = r->d()->locale->toString(date, enumFormat); } - return ctx->d()->engine->newString(formattedDate)->asReturnedValue(); + scope.result = scope.engine->newString(formattedDate); } -QV4::ReturnedValue QQmlDateExtension::method_fromLocaleString(QV4::CallContext *ctx) +void QQmlDateExtension::method_fromLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData) { - QV4::ExecutionEngine * const engine = ctx->d()->engine; - if (ctx->argc() == 1) { - if (String *s = ctx->args()[0].stringValue()) { + QV4::ExecutionEngine * const engine = scope.engine; + if (callData->argc == 1) { + if (String *s = callData->args[0].stringValue()) { QLocale locale; QString dateString = s->toQString(); QDateTime dt = locale.toDateTime(dateString); - return QV4::Encode(engine->newDateObject(dt)); + RETURN_RESULT(engine->newDateObject(dt)); } } - QV4::Scope scope(ctx); - - if (ctx->argc() < 1 || ctx->argc() > 3 || !isLocaleObject(ctx->args()[0])) - V4THROW_ERROR("Locale: Date.fromLocaleString(): Invalid arguments"); + if (callData->argc < 1 || callData->argc > 3 || !isLocaleObject(callData->args[0])) + THROW_ERROR("Locale: Date.fromLocaleString(): Invalid arguments"); - GET_LOCALE_DATA_RESOURCE(ctx->args()[0]); + GET_LOCALE_DATA_RESOURCE(callData->args[0]); QLocale::FormatType enumFormat = QLocale::LongFormat; QDateTime dt; - QString dateString = ctx->args()[1].toQStringNoThrow(); - if (ctx->argc() == 3) { - if (String *s = ctx->args()[2].stringValue()) { + QString dateString = callData->args[1].toQStringNoThrow(); + if (callData->argc == 3) { + if (String *s = callData->args[2].stringValue()) { QString format = s->toQString(); dt = r->d()->locale->toDateTime(dateString, format); - } else if (ctx->args()[2].isNumber()) { - quint32 intFormat = ctx->args()[2].toNumber(); + } else if (callData->args[2].isNumber()) { + quint32 intFormat = callData->args[2].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); dt = r->d()->locale->toDateTime(dateString, format); } else { - V4THROW_ERROR("Locale: Date.fromLocaleString(): Invalid datetime format"); + THROW_ERROR("Locale: Date.fromLocaleString(): Invalid datetime format"); } } else { dt = r->d()->locale->toDateTime(dateString, enumFormat); } - return QV4::Encode(engine->newDateObject(dt)); + scope.result = engine->newDateObject(dt); } -QV4::ReturnedValue QQmlDateExtension::method_fromLocaleTimeString(QV4::CallContext *ctx) +void QQmlDateExtension::method_fromLocaleTimeString(const BuiltinFunction *, Scope &scope, CallData *callData) { - QV4::ExecutionEngine * const engine = ctx->d()->engine; + QV4::ExecutionEngine * const engine = scope.engine; - if (ctx->argc() == 1) { - if (String *s = ctx->args()[0].stringValue()) { + if (callData->argc == 1) { + if (String *s = callData->args[0].stringValue()) { QLocale locale; QString timeString = s->toQString(); QTime time = locale.toTime(timeString); QDateTime dt = QDateTime::currentDateTime(); dt.setTime(time); - return QV4::Encode(engine->newDateObject(dt)); + RETURN_RESULT(engine->newDateObject(dt)); } } - if (ctx->argc() < 1 || ctx->argc() > 3 || !isLocaleObject(ctx->args()[0])) - V4THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid arguments"); - - QV4::Scope scope(ctx); + if (callData->argc < 1 || callData->argc > 3 || !isLocaleObject(callData->args[0])) + THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid arguments"); - GET_LOCALE_DATA_RESOURCE(ctx->args()[0]); + GET_LOCALE_DATA_RESOURCE(callData->args[0]); QLocale::FormatType enumFormat = QLocale::LongFormat; QTime tm; - QString dateString = ctx->args()[1].toQStringNoThrow(); - if (ctx->argc() == 3) { - if (String *s = ctx->args()[2].stringValue()) { + QString dateString = callData->args[1].toQStringNoThrow(); + if (callData->argc == 3) { + if (String *s = callData->args[2].stringValue()) { QString format = s->toQString(); tm = r->d()->locale->toTime(dateString, format); - } else if (ctx->args()[2].isNumber()) { - quint32 intFormat = ctx->args()[2].toNumber(); + } else if (callData->args[2].isNumber()) { + quint32 intFormat = callData->args[2].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); tm = r->d()->locale->toTime(dateString, format); } else { - V4THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid datetime format"); + THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid datetime format"); } } else { tm = r->d()->locale->toTime(dateString, enumFormat); @@ -300,58 +311,56 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleTimeString(QV4::CallConte dt.setTime(tm); } - return QV4::Encode(engine->newDateObject(dt)); + RETURN_RESULT(engine->newDateObject(dt)); } -QV4::ReturnedValue QQmlDateExtension::method_fromLocaleDateString(QV4::CallContext *ctx) +void QQmlDateExtension::method_fromLocaleDateString(const BuiltinFunction *, Scope &scope, CallData *callData) { - QV4::ExecutionEngine * const engine = ctx->d()->engine; + QV4::ExecutionEngine * const engine = scope.engine; - if (ctx->argc() == 1) { - if (String *s = ctx->args()[0].stringValue()) { + if (callData->argc == 1) { + if (String *s = callData->args[0].stringValue()) { QLocale locale; QString dateString = s->toQString(); QDate date = locale.toDate(dateString); - return QV4::Encode(engine->newDateObject(QDateTime(date))); + RETURN_RESULT(engine->newDateObject(QDateTime(date))); } } - if (ctx->argc() < 1 || ctx->argc() > 3 || !isLocaleObject(ctx->args()[0])) - V4THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid arguments"); + if (callData->argc < 1 || callData->argc > 3 || !isLocaleObject(callData->args[0])) + THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid arguments"); - QV4::Scope scope(ctx); - - GET_LOCALE_DATA_RESOURCE(ctx->args()[0]); + GET_LOCALE_DATA_RESOURCE(callData->args[0]); QLocale::FormatType enumFormat = QLocale::LongFormat; QDate dt; - QString dateString = ctx->args()[1].toQStringNoThrow(); - if (ctx->argc() == 3) { - if (String *s = ctx->args()[2].stringValue()) { + QString dateString = callData->args[1].toQStringNoThrow(); + if (callData->argc == 3) { + if (String *s = callData->args[2].stringValue()) { QString format = s->toQString(); dt = r->d()->locale->toDate(dateString, format); - } else if (ctx->args()[2].isNumber()) { - quint32 intFormat = ctx->args()[2].toNumber(); + } else if (callData->args[2].isNumber()) { + quint32 intFormat = callData->args[2].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); dt = r->d()->locale->toDate(dateString, format); } else { - V4THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid datetime format"); + THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid datetime format"); } } else { dt = r->d()->locale->toDate(dateString, enumFormat); } - return QV4::Encode(engine->newDateObject(QDateTime(dt))); + RETURN_RESULT(engine->newDateObject(QDateTime(dt))); } -QV4::ReturnedValue QQmlDateExtension::method_timeZoneUpdated(QV4::CallContext *ctx) +void QQmlDateExtension::method_timeZoneUpdated(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 0) - V4THROW_ERROR("Locale: Date.timeZoneUpdated(): Invalid arguments"); + if (callData->argc != 0) + THROW_ERROR("Locale: Date.timeZoneUpdated(): Invalid arguments"); QV4::DatePrototype::timezoneUpdated(); - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } //----------------- @@ -364,148 +373,143 @@ void QQmlNumberExtension::registerExtension(QV4::ExecutionEngine *engine) engine->numberCtor()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString); } -QV4::ReturnedValue QQmlNumberExtension::method_toLocaleString(QV4::CallContext *ctx) +void QQmlNumberExtension::method_toLocaleString(const BuiltinFunction *b, Scope &scope, CallData *callData) { - if (ctx->argc() > 3) - V4THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments"); + if (callData->argc > 3) + THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments"); - double number = ctx->thisObject().toNumber(); + double number = callData->thisObject.toNumber(); - if (ctx->argc() == 0) { + if (callData->argc == 0) { // Use QLocale for standard toLocaleString() function QLocale locale; - return ctx->d()->engine->newString(locale.toString(number))->asReturnedValue(); + RETURN_RESULT(scope.engine->newString(locale.toString(number))); } - if (!isLocaleObject(ctx->args()[0])) - return QV4::NumberPrototype::method_toLocaleString(ctx); // Use the default Number toLocaleString() - - QV4::Scope scope(ctx); + if (!isLocaleObject(callData->args[0])) { + QV4::NumberPrototype::method_toLocaleString(b, scope, callData); // Use the default Number toLocaleString() + return; + } - GET_LOCALE_DATA_RESOURCE(ctx->args()[0]); + GET_LOCALE_DATA_RESOURCE(callData->args[0]); quint16 format = 'f'; - if (ctx->argc() > 1) { - if (!ctx->args()[1].isString()) - V4THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments"); - QString fs = ctx->args()[1].toQString(); + if (callData->argc > 1) { + if (!callData->args[1].isString()) + THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments"); + QString fs = callData->args[1].toQString(); if (fs.length()) format = fs.at(0).unicode(); } int prec = 2; - if (ctx->argc() > 2) { - if (!ctx->args()[2].isNumber()) - V4THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments"); - prec = ctx->args()[2].toInt32(); + if (callData->argc > 2) { + if (!callData->args[2].isNumber()) + THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments"); + prec = callData->args[2].toInt32(); } - return ctx->d()->engine->newString(r->d()->locale->toString(number, (char)format, prec))->asReturnedValue(); + scope.result = scope.engine->newString(r->d()->locale->toString(number, (char)format, prec)); } -QV4::ReturnedValue QQmlNumberExtension::method_toLocaleCurrencyString(QV4::CallContext *ctx) +void QQmlNumberExtension::method_toLocaleCurrencyString(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() > 2) - V4THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments"); + if (callData->argc > 2) + THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments"); - double number = ctx->thisObject().toNumber(); + double number = callData->thisObject.toNumber(); - if (ctx->argc() == 0) { + if (callData->argc == 0) { // Use QLocale for standard toLocaleString() function QLocale locale; - return ctx->d()->engine->newString(locale.toString(number))->asReturnedValue(); + RETURN_RESULT(scope.engine->newString(locale.toString(number))); } - if (!isLocaleObject(ctx->args()[0])) - V4THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments"); - - QV4::Scope scope(ctx); + if (!isLocaleObject(callData->args[0])) + THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments"); - GET_LOCALE_DATA_RESOURCE(ctx->args()[0]); + GET_LOCALE_DATA_RESOURCE(callData->args[0]); QString symbol; - if (ctx->argc() > 1) { - if (!ctx->args()[1].isString()) - V4THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments"); - symbol = ctx->args()[1].toQStringNoThrow(); + if (callData->argc > 1) { + if (!callData->args[1].isString()) + THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments"); + symbol = callData->args[1].toQStringNoThrow(); } - return ctx->d()->engine->newString(r->d()->locale->toCurrencyString(number, symbol))->asReturnedValue(); + RETURN_RESULT(scope.engine->newString(r->d()->locale->toCurrencyString(number, symbol))); } -QV4::ReturnedValue QQmlNumberExtension::method_fromLocaleString(QV4::CallContext *ctx) +void QQmlNumberExtension::method_fromLocaleString(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() < 1 || ctx->argc() > 2) - V4THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments"); + if (callData->argc < 1 || callData->argc > 2) + THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments"); int numberIdx = 0; QLocale locale; - QV4::Scope scope(ctx); - - if (ctx->argc() == 2) { - if (!isLocaleObject(ctx->args()[0])) - V4THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments"); + if (callData->argc == 2) { + if (!isLocaleObject(callData->args[0])) + THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments"); - GET_LOCALE_DATA_RESOURCE(ctx->args()[0]); + GET_LOCALE_DATA_RESOURCE(callData->args[0]); locale = *r->d()->locale; numberIdx = 1; } - QString ns = ctx->args()[numberIdx].toQString(); + QString ns = callData->args[numberIdx].toQString(); if (!ns.length()) - return QV4::Encode(Q_QNAN); + RETURN_RESULT(QV4::Encode(Q_QNAN)); bool ok = false; double val = locale.toDouble(ns, &ok); if (!ok) - V4THROW_ERROR("Locale: Number.fromLocaleString(): Invalid format") + THROW_ERROR("Locale: Number.fromLocaleString(): Invalid format"); - return QV4::Encode(val); + scope.result = QV4::Encode(val); } //-------------- // Locale object -QV4::ReturnedValue QQmlLocaleData::method_get_firstDayOfWeek(QV4::CallContext *ctx) +void QQmlLocaleData::method_get_firstDayOfWeek(const BuiltinFunction *, Scope &scope, CallData *callData) { - QLocale *locale = getThisLocale(ctx); + QLocale *locale = getThisLocale(scope, callData); if (!locale) - return QV4::Encode::undefined(); + return; int fdow = int(locale->firstDayOfWeek()); if (fdow == 7) fdow = 0; // Qt::Sunday = 7, but Sunday is 0 in JS Date - return QV4::Encode(fdow); + scope.result = QV4::Encode(fdow); } -QV4::ReturnedValue QQmlLocaleData::method_get_measurementSystem(QV4::CallContext *ctx) +void QQmlLocaleData::method_get_measurementSystem(const BuiltinFunction *, Scope &scope, CallData *callData) { - QLocale *locale = getThisLocale(ctx); + QLocale *locale = getThisLocale(scope, callData); if (!locale) - return QV4::Encode::undefined(); - return QV4::Encode(locale->measurementSystem()); + return; + scope.result = QV4::Encode(locale->measurementSystem()); } -QV4::ReturnedValue QQmlLocaleData::method_get_textDirection(QV4::CallContext *ctx) +void QQmlLocaleData::method_get_textDirection(const BuiltinFunction *, Scope &scope, CallData *callData) { - QLocale *locale = getThisLocale(ctx); + QLocale *locale = getThisLocale(scope, callData); if (!locale) - return QV4::Encode::undefined(); + return; - return QV4::Encode(locale->textDirection()); + scope.result = QV4::Encode(locale->textDirection()); } -QV4::ReturnedValue QQmlLocaleData::method_get_weekDays(QV4::CallContext *ctx) +void QQmlLocaleData::method_get_weekDays(const BuiltinFunction *, Scope &scope, CallData *callData) { - QV4::Scope scope(ctx); - QLocale *locale = getThisLocale(ctx); + QLocale *locale = getThisLocale(scope, callData); if (!locale) - return QV4::Encode::undefined(); + return; QList days = locale->weekdays(); - QV4::ScopedArrayObject result(scope, ctx->d()->engine->newArrayObject()); + QV4::ScopedArrayObject result(scope, scope.engine->newArrayObject()); result->arrayReserve(days.size()); for (int i = 0; i < days.size(); ++i) { int day = days.at(i); @@ -515,59 +519,58 @@ QV4::ReturnedValue QQmlLocaleData::method_get_weekDays(QV4::CallContext *ctx) } result->setArrayLengthUnchecked(days.size()); - return result.asReturnedValue(); + scope.result = result.asReturnedValue(); } -QV4::ReturnedValue QQmlLocaleData::method_get_uiLanguages(QV4::CallContext *ctx) +void QQmlLocaleData::method_get_uiLanguages(const BuiltinFunction *, Scope &scope, CallData *callData) { - QV4::Scope scope(ctx); - QLocale *locale = getThisLocale(ctx); + QLocale *locale = getThisLocale(scope, callData); if (!locale) - return QV4::Encode::undefined(); + return; QStringList langs = locale->uiLanguages(); - QV4::ScopedArrayObject result(scope, ctx->d()->engine->newArrayObject()); + QV4::ScopedArrayObject result(scope, scope.engine->newArrayObject()); result->arrayReserve(langs.size()); QV4::ScopedValue v(scope); for (int i = 0; i < langs.size(); ++i) - result->arrayPut(i, (v = ctx->d()->engine->newString(langs.at(i)))); + result->arrayPut(i, (v = scope.engine->newString(langs.at(i)))); result->setArrayLengthUnchecked(langs.size()); - return result.asReturnedValue(); + scope.result = result.asReturnedValue(); } -QV4::ReturnedValue QQmlLocaleData::method_currencySymbol(QV4::CallContext *ctx) +void QQmlLocaleData::method_currencySymbol(const BuiltinFunction *, Scope &scope, CallData *callData) { - QLocale *locale = getThisLocale(ctx); + QLocale *locale = getThisLocale(scope, callData); if (!locale) - return QV4::Encode::undefined(); + return; - if (ctx->argc() > 1) - V4THROW_ERROR("Locale: currencySymbol(): Invalid arguments"); + if (callData->argc > 1) + THROW_ERROR("Locale: currencySymbol(): Invalid arguments"); QLocale::CurrencySymbolFormat format = QLocale::CurrencySymbol; - if (ctx->argc() == 1) { - quint32 intFormat = ctx->args()[0].toNumber(); + if (callData->argc == 1) { + quint32 intFormat = callData->args[0].toNumber(); format = QLocale::CurrencySymbolFormat(intFormat); } - return ctx->d()->engine->newString(locale->currencySymbol(format))->asReturnedValue(); + scope.result = scope.engine->newString(locale->currencySymbol(format)); } #define LOCALE_FORMAT(FUNC) \ -QV4::ReturnedValue QQmlLocaleData::method_ ##FUNC (QV4::CallContext *ctx) { \ - QLocale *locale = getThisLocale(ctx); \ +void QQmlLocaleData::method_ ##FUNC (const BuiltinFunction *, Scope &scope, CallData *callData) { \ + QLocale *locale = getThisLocale(scope, callData); \ if (!locale) \ - return QV4::Encode::undefined(); \ - if (ctx->argc() > 1) \ - V4THROW_ERROR("Locale: " #FUNC "(): Invalid arguments"); \ + return; \ + if (callData->argc > 1) \ + THROW_ERROR("Locale: " #FUNC "(): Invalid arguments"); \ QLocale::FormatType format = QLocale::LongFormat;\ - if (ctx->argc() == 1) { \ - quint32 intFormat = ctx->args()[0].toUInt32(); \ + if (callData->argc == 1) { \ + quint32 intFormat = callData->args[0].toUInt32(); \ format = QLocale::FormatType(intFormat); \ } \ - return ctx->engine()->newString(locale-> FUNC (format))->asReturnedValue(); \ + scope.result = scope.engine->newString(locale-> FUNC (format)); \ } LOCALE_FORMAT(dateTimeFormat) @@ -576,57 +579,57 @@ LOCALE_FORMAT(dateFormat) // +1 added to idx because JS is 0-based, whereas QLocale months begin at 1. #define LOCALE_FORMATTED_MONTHNAME(VARIABLE) \ -QV4::ReturnedValue QQmlLocaleData::method_ ## VARIABLE (QV4::CallContext *ctx) {\ - QLocale *locale = getThisLocale(ctx); \ +void QQmlLocaleData::method_ ## VARIABLE (const BuiltinFunction *, Scope &scope, CallData *callData) {\ + QLocale *locale = getThisLocale(scope, callData); \ if (!locale) \ - return QV4::Encode::undefined(); \ - if (ctx->argc() < 1 || ctx->argc() > 2) \ - V4THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \ + return; \ + if (callData->argc < 1 || callData->argc > 2) \ + THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \ QLocale::FormatType enumFormat = QLocale::LongFormat; \ - int idx = ctx->args()[0].toInt32() + 1; \ + int idx = callData->args[0].toInt32() + 1; \ if (idx < 1 || idx > 12) \ - V4THROW_ERROR("Locale: Invalid month"); \ + THROW_ERROR("Locale: Invalid month"); \ QString name; \ - if (ctx->argc() == 2) { \ - if (ctx->args()[1].isNumber()) { \ - quint32 intFormat = ctx->args()[1].toUInt32(); \ + if (callData->argc == 2) { \ + if (callData->args[1].isNumber()) { \ + quint32 intFormat = callData->args[1].toUInt32(); \ QLocale::FormatType format = QLocale::FormatType(intFormat); \ name = locale-> VARIABLE(idx, format); \ } else { \ - V4THROW_ERROR("Locale: Invalid datetime format"); \ + THROW_ERROR("Locale: Invalid datetime format"); \ } \ } else { \ name = locale-> VARIABLE(idx, enumFormat); \ } \ - return ctx->engine()->newString(name)->asReturnedValue(); \ + scope.result = scope.engine->newString(name); \ } // 0 -> 7 as Qt::Sunday is 7, but Sunday is 0 in JS Date #define LOCALE_FORMATTED_DAYNAME(VARIABLE) \ -QV4::ReturnedValue QQmlLocaleData::method_ ## VARIABLE (QV4::CallContext *ctx) {\ - QLocale *locale = getThisLocale(ctx); \ +void QQmlLocaleData::method_ ## VARIABLE (const BuiltinFunction *, Scope &scope, CallData *callData) {\ + QLocale *locale = getThisLocale(scope, callData); \ if (!locale) \ - return QV4::Encode::undefined(); \ - if (ctx->argc() < 1 || ctx->argc() > 2) \ - V4THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \ + return; \ + if (callData->argc < 1 || callData->argc > 2) \ + THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \ QLocale::FormatType enumFormat = QLocale::LongFormat; \ - int idx = ctx->args()[0].toInt32(); \ + int idx = callData->args[0].toInt32(); \ if (idx < 0 || idx > 7) \ - V4THROW_ERROR("Locale: Invalid day"); \ + THROW_ERROR("Locale: Invalid day"); \ if (idx == 0) idx = 7; \ QString name; \ - if (ctx->argc() == 2) { \ - if (ctx->args()[1].isNumber()) { \ - quint32 intFormat = ctx->args()[1].toUInt32(); \ + if (callData->argc == 2) { \ + if (callData->args[1].isNumber()) { \ + quint32 intFormat = callData->args[1].toUInt32(); \ QLocale::FormatType format = QLocale::FormatType(intFormat); \ name = locale-> VARIABLE(idx, format); \ } else { \ - V4THROW_ERROR("Locale: Invalid datetime format"); \ + THROW_ERROR("Locale: Invalid datetime format"); \ } \ } else { \ name = locale-> VARIABLE(idx, enumFormat); \ } \ - return ctx->engine()->newString(name)->asReturnedValue(); \ + scope.result = scope.engine->newString(name); \ } LOCALE_FORMATTED_MONTHNAME(monthName) @@ -634,12 +637,12 @@ LOCALE_FORMATTED_MONTHNAME(standaloneMonthName) LOCALE_FORMATTED_DAYNAME(dayName) LOCALE_FORMATTED_DAYNAME(standaloneDayName) -#define LOCALE_STRING_PROPERTY(VARIABLE) QV4::ReturnedValue QQmlLocaleData::method_get_ ## VARIABLE (QV4::CallContext* ctx) \ +#define LOCALE_STRING_PROPERTY(VARIABLE) void QQmlLocaleData::method_get_ ## VARIABLE (const BuiltinFunction *, Scope &scope, CallData *callData) \ { \ - QLocale *locale = getThisLocale(ctx); \ + QLocale *locale = getThisLocale(scope, callData); \ if (!locale) \ - return QV4::Encode::undefined(); \ - return ctx->engine()->newString(locale-> VARIABLE())->asReturnedValue();\ + return; \ + scope.result = scope.engine->newString(locale-> VARIABLE());\ } LOCALE_STRING_PROPERTY(name) @@ -830,18 +833,22 @@ void QQmlLocale::registerStringLocaleCompare(QV4::ExecutionEngine *engine) engine->stringPrototype()->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare); } -QV4::ReturnedValue QQmlLocale::method_localeCompare(QV4::CallContext *ctx) +void QQmlLocale::method_localeCompare(const BuiltinFunction *b, Scope &scope, CallData *callData) { - if (ctx->argc() != 1 || (!ctx->args()[0].isString() && !ctx->args()[0].as())) - return QV4::StringPrototype::method_localeCompare(ctx); + if (callData->argc != 1 || (!callData->args[0].isString() && !callData->args[0].as())) { + QV4::StringPrototype::method_localeCompare(b, scope, callData); + return; + } - if (!ctx->thisObject().isString() && !ctx->thisObject().as()) - return QV4::StringPrototype::method_localeCompare(ctx); + if (!callData->thisObject.isString() && !callData->thisObject.as()) { + QV4::StringPrototype::method_localeCompare(b, scope, callData); + return; + } - QString thisString = ctx->thisObject().toQStringNoThrow(); - QString thatString = ctx->args()[0].toQStringNoThrow(); + QString thisString = callData->thisObject.toQStringNoThrow(); + QString thatString = callData->args[0].toQStringNoThrow(); - return QV4::Encode(QString::localeAwareCompare(thisString, thatString)); + scope.result = QV4::Encode(QString::localeAwareCompare(thisString, thatString)); } /*! diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h index 275f58db7d..1a2ffc72b0 100644 --- a/src/qml/qml/qqmllocale_p.h +++ b/src/qml/qml/qqmllocale_p.h @@ -67,13 +67,13 @@ public: static void registerExtension(QV4::ExecutionEngine *engine); private: - static QV4::ReturnedValue method_toLocaleString(QV4::CallContext *ctx); - static QV4::ReturnedValue method_toLocaleTimeString(QV4::CallContext *ctx); - static QV4::ReturnedValue method_toLocaleDateString(QV4::CallContext *ctx); - static QV4::ReturnedValue method_fromLocaleString(QV4::CallContext *ctx); - static QV4::ReturnedValue method_fromLocaleTimeString(QV4::CallContext *ctx); - static QV4::ReturnedValue method_fromLocaleDateString(QV4::CallContext *ctx); - static QV4::ReturnedValue method_timeZoneUpdated(QV4::CallContext *ctx); + static void method_toLocaleString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_toLocaleTimeString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_toLocaleDateString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_fromLocaleString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_fromLocaleTimeString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_fromLocaleDateString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_timeZoneUpdated(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); }; @@ -83,9 +83,9 @@ public: static void registerExtension(QV4::ExecutionEngine *engine); private: - static QV4::ReturnedValue method_toLocaleString(QV4::CallContext *ctx); - static QV4::ReturnedValue method_fromLocaleString(QV4::CallContext *ctx); - static QV4::ReturnedValue method_toLocaleCurrencyString(QV4::CallContext *ctx); + static void method_toLocaleString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_fromLocaleString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_toLocaleCurrencyString(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); }; @@ -135,7 +135,7 @@ public: private: QQmlLocale(); - static QV4::ReturnedValue method_localeCompare(QV4::CallContext *ctx); + static void method_localeCompare(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); }; namespace QV4 { @@ -158,43 +158,43 @@ struct QQmlLocaleData : public QV4::Object V4_OBJECT2(QQmlLocaleData, Object) V4_NEEDS_DESTROY - static QLocale *getThisLocale(QV4::CallContext *ctx) { - QV4::Object *o = ctx->thisObject().as(); + static QLocale *getThisLocale(QV4::Scope &scope, QV4::CallData *callData) { + QV4::Object *o = callData->thisObject.as(); QQmlLocaleData *thisObject = o ? o->as() : 0; if (!thisObject) { - ctx->engine()->throwTypeError(); + scope.engine->throwTypeError(); return 0; } return thisObject->d()->locale; } - static QV4::ReturnedValue method_currencySymbol(QV4::CallContext *ctx); - static QV4::ReturnedValue method_dateTimeFormat(QV4::CallContext *ctx); - static QV4::ReturnedValue method_timeFormat(QV4::CallContext *ctx); - static QV4::ReturnedValue method_dateFormat(QV4::CallContext *ctx); - static QV4::ReturnedValue method_monthName(QV4::CallContext *ctx); - static QV4::ReturnedValue method_standaloneMonthName(QV4::CallContext *ctx); - static QV4::ReturnedValue method_dayName(QV4::CallContext *ctx); - static QV4::ReturnedValue method_standaloneDayName(QV4::CallContext *ctx); - - static QV4::ReturnedValue method_get_firstDayOfWeek(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_measurementSystem(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_textDirection(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_weekDays(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_uiLanguages(QV4::CallContext *ctx); - - static QV4::ReturnedValue method_get_name(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_nativeLanguageName(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_nativeCountryName(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_decimalPoint(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_groupSeparator(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_percent(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_zeroDigit(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_negativeSign(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_positiveSign(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_exponential(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_amText(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_pmText(QV4::CallContext *ctx); + static void method_currencySymbol(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_dateTimeFormat(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_timeFormat(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_dateFormat(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_monthName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_standaloneMonthName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_dayName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_standaloneDayName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + + static void method_get_firstDayOfWeek(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_measurementSystem(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_textDirection(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_weekDays(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_uiLanguages(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + + static void method_get_name(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_nativeLanguageName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_nativeCountryName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_decimalPoint(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_groupSeparator(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_percent(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_zeroDigit(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_negativeSign(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_positiveSign(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_exponential(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_amText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_pmText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); }; } -- cgit v1.2.3 From 119e2edb3ea52a6b3b9da6183dc0fcf350ba8431 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 5 Jan 2017 15:14:37 +0100 Subject: Convert more builtin functions Change-Id: I2dc8797e2240fcfc4176cb08b982e3e98b879646 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4errorobject.cpp | 25 +++--- src/qml/jsruntime/qv4errorobject_p.h | 4 +- src/qml/jsruntime/qv4functionobject.cpp | 75 ++++++++-------- src/qml/jsruntime/qv4functionobject_p.h | 8 +- src/qml/jsruntime/qv4global_p.h | 1 + src/qml/jsruntime/qv4globalobject.cpp | 146 +++++++++++++++----------------- src/qml/jsruntime/qv4globalobject_p.h | 20 ++--- src/qml/jsruntime/qv4include.cpp | 19 ++--- src/qml/jsruntime/qv4include_p.h | 2 +- src/qml/jsruntime/qv4jsonobject.cpp | 23 +++-- src/qml/jsruntime/qv4jsonobject_p.h | 4 +- src/qml/jsruntime/qv4regexpobject.cpp | 94 +++++++++----------- src/qml/jsruntime/qv4regexpobject_p.h | 18 ++-- src/qml/jsruntime/qv4scopedvalue_p.h | 4 +- 14 files changed, 206 insertions(+), 237 deletions(-) diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index 597ded6ae1..f290bc5136 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -153,12 +153,11 @@ const char *ErrorObject::className(Heap::ErrorObject::ErrorType t) Q_UNREACHABLE(); } -ReturnedValue ErrorObject::method_get_stack(CallContext *ctx) +void ErrorObject::method_get_stack(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped This(scope, ctx->thisObject()); + Scoped This(scope, callData->thisObject); if (!This) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); if (!This->d()->stack) { QString trace; for (int i = 0; i < This->d()->stackTrace->count(); ++i) { @@ -169,9 +168,9 @@ ReturnedValue ErrorObject::method_get_stack(CallContext *ctx) if (frame.line >= 0) trace += QLatin1Char(':') + QString::number(frame.line); } - This->d()->stack = ctx->d()->engine->newString(trace); + This->d()->stack = scope.engine->newString(trace); } - return This->d()->stack->asReturnedValue(); + scope.result = This->d()->stack; } void ErrorObject::markObjects(Heap::Base *that, ExecutionEngine *e) @@ -335,22 +334,20 @@ void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj, He obj->defineDefaultProperty(engine->id_toString(), method_toString, 0); } -ReturnedValue ErrorPrototype::method_toString(CallContext *ctx) +void ErrorPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - - Object *o = ctx->thisObject().as(); + Object *o = callData->thisObject.as(); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - ScopedValue name(scope, o->get(ctx->d()->engine->id_name())); + ScopedValue name(scope, o->get(scope.engine->id_name())); QString qname; if (name->isUndefined()) qname = QStringLiteral("Error"); else qname = name->toQString(); - ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("message"))); + ScopedString s(scope, scope.engine->newString(QStringLiteral("message"))); ScopedValue message(scope, o->get(s)); QString qmessage; if (!message->isUndefined()) @@ -365,5 +362,5 @@ ReturnedValue ErrorPrototype::method_toString(CallContext *ctx) str = qname + QLatin1String(": ") + qmessage; } - return ctx->d()->engine->newString(str)->asReturnedValue(); + scope.result = scope.engine->newString(str)->asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h index 2b3ab25e2d..9ba9f05234 100644 --- a/src/qml/jsruntime/qv4errorobject_p.h +++ b/src/qml/jsruntime/qv4errorobject_p.h @@ -172,7 +172,7 @@ struct ErrorObject: Object { static const char *className(Heap::ErrorObject::ErrorType t); - static ReturnedValue method_get_stack(CallContext *ctx); + static void method_get_stack(const BuiltinFunction *, Scope &scope, CallData *callData); static void markObjects(Heap::Base *that, ExecutionEngine *e); }; @@ -282,7 +282,7 @@ struct ErrorPrototype : ErrorObject void init(ExecutionEngine *engine, Object *ctor) { init(engine, ctor, this, Heap::ErrorObject::Error); } static void init(ExecutionEngine *engine, Object *ctor, Object *obj, Heap::ErrorObject::ErrorType t); - static ReturnedValue method_toString(CallContext *ctx); + static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); }; struct EvalErrorPrototype : ErrorObject diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 1458c77d88..b2d89220ea 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -270,23 +270,22 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor) } -ReturnedValue FunctionPrototype::method_toString(CallContext *ctx) +void FunctionPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) { - FunctionObject *fun = ctx->thisObject().as(); + FunctionObject *fun = callData->thisObject.as(); if (!fun) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - return ctx->d()->engine->newString(QStringLiteral("function() { [code] }"))->asReturnedValue(); + scope.result = scope.engine->newString(QStringLiteral("function() { [code] }")); } -ReturnedValue FunctionPrototype::method_apply(CallContext *ctx) +void FunctionPrototype::method_apply(const BuiltinFunction *, Scope &scope, CallData *callData) { - FunctionObject *o = ctx->thisObject().as(); + FunctionObject *o = callData->thisObject.as(); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - Scope scope(ctx); - ScopedValue arg(scope, ctx->argument(1)); + ScopedValue arg(scope, callData->argument(1)); ScopedObject arr(scope, arg); @@ -294,75 +293,71 @@ ReturnedValue FunctionPrototype::method_apply(CallContext *ctx) if (!arr) { len = 0; if (!arg->isNullOrUndefined()) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); } else { len = arr->getLength(); } - ScopedCallData callData(scope, len); + ScopedCallData cData(scope, len); if (len) { if (ArgumentsObject::isNonStrictArgumentsObject(arr) && !arr->cast()->fullyCreated()) { QV4::ArgumentsObject *a = arr->cast(); int l = qMin(len, (uint)a->d()->context->callData->argc); - memcpy(callData->args, a->d()->context->callData->args, l*sizeof(Value)); + memcpy(cData->args, a->d()->context->callData->args, l*sizeof(Value)); for (quint32 i = l; i < len; ++i) - callData->args[i] = Primitive::undefinedValue(); + cData->args[i] = Primitive::undefinedValue(); } else if (arr->arrayType() == Heap::ArrayData::Simple && !arr->protoHasArray()) { auto sad = static_cast(arr->arrayData()); uint alen = sad ? sad->len : 0; if (alen > len) alen = len; for (uint i = 0; i < alen; ++i) - callData->args[i] = sad->data(i); + cData->args[i] = sad->data(i); for (quint32 i = alen; i < len; ++i) - callData->args[i] = Primitive::undefinedValue(); + cData->args[i] = Primitive::undefinedValue(); } else { for (quint32 i = 0; i < len; ++i) - callData->args[i] = arr->getIndexed(i); + cData->args[i] = arr->getIndexed(i); } } - callData->thisObject = ctx->argument(0); - o->call(scope, callData); - return scope.result.asReturnedValue(); + cData->thisObject = callData->argument(0); + o->call(scope, cData); } -ReturnedValue FunctionPrototype::method_call(CallContext *ctx) +void FunctionPrototype::method_call(const BuiltinFunction *, Scope &scope, CallData *callData) { - FunctionObject *o = ctx->thisObject().as(); + FunctionObject *o = callData->thisObject.as(); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - Scope scope(ctx); - ScopedCallData callData(scope, ctx->argc() ? ctx->argc() - 1 : 0); - if (ctx->argc()) { - for (int i = 1; i < ctx->argc(); ++i) - callData->args[i - 1] = ctx->args()[i]; + ScopedCallData cData(scope, callData->argc ? callData->argc - 1 : 0); + if (callData->argc) { + for (int i = 1; i < callData->argc; ++i) + cData->args[i - 1] = callData->args[i]; } - callData->thisObject = ctx->argument(0); + cData->thisObject = callData->argument(0); - o->call(scope, callData); - return scope.result.asReturnedValue(); + o->call(scope, cData); } -ReturnedValue FunctionPrototype::method_bind(CallContext *ctx) +void FunctionPrototype::method_bind(const BuiltinFunction *, Scope &scope, CallData *callData) { - FunctionObject *target = ctx->thisObject().as(); + FunctionObject *target = callData->thisObject.as(); if (!target) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - Scope scope(ctx); - ScopedValue boundThis(scope, ctx->argument(0)); + ScopedValue boundThis(scope, callData->argument(0)); Scoped boundArgs(scope, (Heap::MemberData *)0); - if (ctx->argc() > 1) { - boundArgs = MemberData::allocate(scope.engine, ctx->argc() - 1); - boundArgs->d()->size = ctx->argc() - 1; - memcpy(boundArgs->data(), ctx->args() + 1, (ctx->argc() - 1)*sizeof(Value)); + if (callData->argc > 1) { + boundArgs = MemberData::allocate(scope.engine, callData->argc - 1); + boundArgs->d()->size = callData->argc - 1; + memcpy(boundArgs->data(), callData->args + 1, (callData->argc - 1)*sizeof(Value)); } ExecutionContext *global = scope.engine->rootContext(); - return BoundFunction::create(global, target, boundThis, boundArgs)->asReturnedValue(); + scope.result = BoundFunction::create(global, target, boundThis, boundArgs); } DEFINE_OBJECT_VTABLE(ScriptFunction); diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 31b05666a7..45d7485f1b 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -184,10 +184,10 @@ struct FunctionPrototype: FunctionObject void init(ExecutionEngine *engine, Object *ctor); - static ReturnedValue method_toString(CallContext *ctx); - static ReturnedValue method_apply(CallContext *ctx); - static ReturnedValue method_call(CallContext *ctx); - static ReturnedValue method_bind(CallContext *ctx); + static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_apply(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_call(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_bind(const BuiltinFunction *, Scope &scope, CallData *callData); }; struct Q_QML_EXPORT OldBuiltinFunction : FunctionObject { diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index 1dbc538be2..66861bf697 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -208,6 +208,7 @@ struct StringObject; struct ArrayObject; struct DateObject; struct FunctionObject; +struct BuiltinFunction; struct ErrorObject; struct ArgumentsObject; struct Managed; diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index af92ce1ad8..1bc91f832b 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -423,18 +423,15 @@ static inline int toInt(const QChar &qc, int R) } // parseInt [15.1.2.2] -ReturnedValue GlobalFunctions::method_parseInt(CallContext *ctx) +void GlobalFunctions::method_parseInt(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedValue inputString(scope, ctx->argument(0)); - ScopedValue radix(scope, ctx->argument(1)); + ScopedValue inputString(scope, callData->argument(0)); + ScopedValue radix(scope, callData->argument(1)); int R = radix->isUndefined() ? 0 : radix->toInt32(); // [15.1.2.2] step by step: QString trimmed = inputString->toQString().trimmed(); // 1 + 2 - - if (ctx->d()->engine->hasException) - return Encode::undefined(); + CHECK_EXCEPTION(); const QChar *pos = trimmed.constData(); const QChar *end = pos + trimmed.length(); @@ -449,7 +446,7 @@ ReturnedValue GlobalFunctions::method_parseInt(CallContext *ctx) bool stripPrefix = true; // 7 if (R) { // 8 if (R < 2 || R > 36) - return Encode(std::numeric_limits::quiet_NaN()); // 8a + RETURN_RESULT(Encode(std::numeric_limits::quiet_NaN())); // 8a if (R != 16) stripPrefix = false; // 8b } else { // 9 @@ -466,13 +463,13 @@ ReturnedValue GlobalFunctions::method_parseInt(CallContext *ctx) // 11: Z is progressively built below // 13: this is handled by the toInt function if (pos == end) // 12 - return Encode(std::numeric_limits::quiet_NaN()); + RETURN_RESULT(Encode(std::numeric_limits::quiet_NaN())); bool overflow = false; qint64 v_overflow = 0; unsigned overflow_digit_count = 0; int d = toInt(*pos++, R); if (d == -1) - return Encode(std::numeric_limits::quiet_NaN()); + RETURN_RESULT(Encode(std::numeric_limits::quiet_NaN())); qint64 v = d; while (pos != end) { d = toInt(*pos++, R); @@ -499,155 +496,148 @@ ReturnedValue GlobalFunctions::method_parseInt(CallContext *ctx) if (overflow) { double result = (double) v_overflow * pow(static_cast(R), static_cast(overflow_digit_count)); result += v; - return Encode(sign * result); + RETURN_RESULT(Encode(sign * result)); } else { - return Encode(sign * (double) v); // 15 + RETURN_RESULT(Encode(sign * (double) v)); // 15 } } // parseFloat [15.1.2.3] -ReturnedValue GlobalFunctions::method_parseFloat(CallContext *ctx) +void GlobalFunctions::method_parseFloat(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - // [15.1.2.3] step by step: - ScopedString inputString(scope, ctx->argument(0), ScopedString::Convert); - if (scope.engine->hasException) - return Encode::undefined(); + ScopedString inputString(scope, callData->argument(0), ScopedString::Convert); + CHECK_EXCEPTION(); QString trimmed = inputString->toQString().trimmed(); // 2 // 4: if (trimmed.startsWith(QLatin1String("Infinity")) || trimmed.startsWith(QLatin1String("+Infinity"))) - return Encode(Q_INFINITY); + RETURN_RESULT(Encode(Q_INFINITY)); if (trimmed.startsWith(QLatin1String("-Infinity"))) - return Encode(-Q_INFINITY); + RETURN_RESULT(Encode(-Q_INFINITY)); QByteArray ba = trimmed.toLatin1(); bool ok; const char *begin = ba.constData(); const char *end = 0; double d = qstrtod(begin, &end, &ok); if (end - begin == 0) - return Encode(std::numeric_limits::quiet_NaN()); // 3 + RETURN_RESULT(Encode(std::numeric_limits::quiet_NaN())); // 3 else - return Encode(d); + RETURN_RESULT(Encode(d)); } /// isNaN [15.1.2.4] -ReturnedValue GlobalFunctions::method_isNaN(CallContext *ctx) +void GlobalFunctions::method_isNaN(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (!ctx->argc()) + if (!callData->argc) // undefined gets converted to NaN - return Encode(true); + RETURN_RESULT(Encode(true)); - if (ctx->args()[0].integerCompatible()) - return Encode(false); + if (callData->args[0].integerCompatible()) + RETURN_RESULT(Encode(false)); - double d = ctx->args()[0].toNumber(); - return Encode((bool)std::isnan(d)); + double d = callData->args[0].toNumber(); + RETURN_RESULT(Encode((bool)std::isnan(d))); } /// isFinite [15.1.2.5] -ReturnedValue GlobalFunctions::method_isFinite(CallContext *ctx) +void GlobalFunctions::method_isFinite(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (!ctx->argc()) + if (!callData->argc) // undefined gets converted to NaN - return Encode(false); + RETURN_RESULT(Encode(false)); - if (ctx->args()[0].integerCompatible()) - return Encode(true); + if (callData->args[0].integerCompatible()) + RETURN_RESULT(Encode(true)); - double d = ctx->args()[0].toNumber(); - return Encode((bool)std::isfinite(d)); + double d = callData->args[0].toNumber(); + RETURN_RESULT(Encode((bool)std::isfinite(d))); } /// decodeURI [15.1.3.1] -ReturnedValue GlobalFunctions::method_decodeURI(CallContext *context) +void GlobalFunctions::method_decodeURI(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (context->argc() == 0) - return Encode::undefined(); + if (callData->argc == 0) + RETURN_UNDEFINED(); - QString uriString = context->args()[0].toQString(); + QString uriString = callData->args[0].toQString(); bool ok; QString out = decode(uriString, DecodeNonReserved, &ok); if (!ok) { - Scope scope(context); - ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence"))); - return context->engine()->throwURIError(s); + ScopedString s(scope, scope.engine->newString(QStringLiteral("malformed URI sequence"))); + RETURN_RESULT(scope.engine->throwURIError(s)); } - return context->d()->engine->newString(out)->asReturnedValue(); + RETURN_RESULT(scope.engine->newString(out)); } /// decodeURIComponent [15.1.3.2] -ReturnedValue GlobalFunctions::method_decodeURIComponent(CallContext *context) +void GlobalFunctions::method_decodeURIComponent(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (context->argc() == 0) - return Encode::undefined(); + if (callData->argc == 0) + RETURN_UNDEFINED(); - QString uriString = context->args()[0].toQString(); + QString uriString = callData->args[0].toQString(); bool ok; QString out = decode(uriString, DecodeAll, &ok); if (!ok) { - Scope scope(context); - ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence"))); - return context->engine()->throwURIError(s); + ScopedString s(scope, scope.engine->newString(QStringLiteral("malformed URI sequence"))); + RETURN_RESULT(scope.engine->throwURIError(s)); } - return context->d()->engine->newString(out)->asReturnedValue(); + RETURN_RESULT(scope.engine->newString(out)); } /// encodeURI [15.1.3.3] -ReturnedValue GlobalFunctions::method_encodeURI(CallContext *context) +void GlobalFunctions::method_encodeURI(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (context->argc() == 0) - return Encode::undefined(); + if (callData->argc == 0) + RETURN_UNDEFINED(); - QString uriString = context->args()[0].toQString(); + QString uriString = callData->args[0].toQString(); bool ok; QString out = encode(uriString, uriUnescapedReserved, &ok); if (!ok) { - Scope scope(context); - ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence"))); - return context->engine()->throwURIError(s); + ScopedString s(scope, scope.engine->newString(QStringLiteral("malformed URI sequence"))); + RETURN_RESULT(scope.engine->throwURIError(s)); } - return context->d()->engine->newString(out)->asReturnedValue(); + RETURN_RESULT(scope.engine->newString(out)); } /// encodeURIComponent [15.1.3.4] -ReturnedValue GlobalFunctions::method_encodeURIComponent(CallContext *context) +void GlobalFunctions::method_encodeURIComponent(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (context->argc() == 0) - return Encode::undefined(); + if (callData->argc == 0) + RETURN_UNDEFINED(); - QString uriString = context->args()[0].toQString(); + QString uriString = callData->args[0].toQString(); bool ok; QString out = encode(uriString, uriUnescaped, &ok); if (!ok) { - Scope scope(context); - ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence"))); - return context->engine()->throwURIError(s); + ScopedString s(scope, scope.engine->newString(QStringLiteral("malformed URI sequence"))); + RETURN_RESULT(scope.engine->throwURIError(s)); } - return context->d()->engine->newString(out)->asReturnedValue(); + RETURN_RESULT(scope.engine->newString(out)); } -ReturnedValue GlobalFunctions::method_escape(CallContext *context) +void GlobalFunctions::method_escape(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (!context->argc()) - return context->d()->engine->newString(QStringLiteral("undefined"))->asReturnedValue(); + if (!callData->argc) + RETURN_RESULT(scope.engine->newString(QStringLiteral("undefined"))); - QString str = context->args()[0].toQString(); - return context->d()->engine->newString(escape(str))->asReturnedValue(); + QString str = callData->args[0].toQString(); + RETURN_RESULT(scope.engine->newString(escape(str))); } -ReturnedValue GlobalFunctions::method_unescape(CallContext *context) +void GlobalFunctions::method_unescape(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (!context->argc()) - return context->d()->engine->newString(QStringLiteral("undefined"))->asReturnedValue(); + if (!callData->argc) + RETURN_RESULT(scope.engine->newString(QStringLiteral("undefined"))); - QString str = context->args()[0].toQString(); - return context->d()->engine->newString(unescape(str))->asReturnedValue(); + QString str = callData->args[0].toQString(); + RETURN_RESULT(scope.engine->newString(unescape(str))); } diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h index e8b3a92d34..273f1ba7ea 100644 --- a/src/qml/jsruntime/qv4globalobject_p.h +++ b/src/qml/jsruntime/qv4globalobject_p.h @@ -76,16 +76,16 @@ struct Q_QML_EXPORT EvalFunction : FunctionObject struct GlobalFunctions { - static ReturnedValue method_parseInt(CallContext *context); - static ReturnedValue method_parseFloat(CallContext *context); - static ReturnedValue method_isNaN(CallContext *context); - static ReturnedValue method_isFinite(CallContext *ctx); - static ReturnedValue method_decodeURI(CallContext *context); - static ReturnedValue method_decodeURIComponent(CallContext *context); - static ReturnedValue method_encodeURI(CallContext *context); - static ReturnedValue method_encodeURIComponent(CallContext *context); - static ReturnedValue method_escape(CallContext *context); - static ReturnedValue method_unescape(CallContext *context); + static void method_parseInt(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_parseFloat(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_isNaN(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_isFinite(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_decodeURI(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_decodeURIComponent(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_encodeURI(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_encodeURIComponent(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_escape(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_unescape(const BuiltinFunction *, Scope &scope, CallData *callData); }; } diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp index 1d393cf0aa..f033eb2d2d 100644 --- a/src/qml/jsruntime/qv4include.cpp +++ b/src/qml/jsruntime/qv4include.cpp @@ -195,23 +195,22 @@ void QV4Include::finished() /* Documented in qv8engine.cpp */ -QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx) +void QV4Include::method_include(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - if (!ctx->argc()) - return QV4::Encode::undefined(); + if (!callData->argc) + RETURN_UNDEFINED(); - QV4::Scope scope(ctx->engine()); QQmlContextData *context = scope.engine->callingQmlContext(); if (!context || !context->isJSContext) - V4THROW_ERROR("Qt.include(): Can only be called from JavaScript files"); + RETURN_RESULT(scope.engine->throwError(QString::fromUtf8("Qt.include(): Can only be called from JavaScript files"))); QV4::ScopedValue callbackFunction(scope, QV4::Primitive::undefinedValue()); - if (ctx->argc() >= 2 && ctx->args()[1].as()) - callbackFunction = ctx->args()[1]; + if (callData->argc >= 2 && callData->args[1].as()) + callbackFunction = callData->args[1]; #if QT_CONFIG(qml_network) - QUrl url(scope.engine->resolvedUrl(ctx->args()[0].toQStringNoThrow())); + QUrl url(scope.engine->resolvedUrl(callData->args[0].toQStringNoThrow())); if (scope.engine->qmlEngine() && scope.engine->qmlEngine()->urlInterceptor()) url = scope.engine->qmlEngine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::JavaScriptFile); @@ -261,12 +260,12 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx) callback(callbackFunction, result); } - return result->asReturnedValue(); + scope.result = result; #else QV4::ScopedValue result(scope); result = resultValue(scope.engine, NetworkError); callback(callbackFunction, result); - return result->asReturnedValue(); + scope.result = result; #endif } diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h index 4c601a5e7b..5908d6bfde 100644 --- a/src/qml/jsruntime/qv4include_p.h +++ b/src/qml/jsruntime/qv4include_p.h @@ -77,7 +77,7 @@ public: Exception = 3 }; - static QV4::ReturnedValue method_include(QV4::CallContext *ctx); + static void method_include(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); private Q_SLOTS: void finished(); diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index d79e6242ba..1d571f53f3 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -883,10 +883,9 @@ void Heap::JsonObject::init() } -ReturnedValue JsonObject::method_parse(CallContext *ctx) +void JsonObject::method_parse(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedValue v(scope, ctx->argument(0)); + ScopedValue v(scope, callData->argument(0)); QString jtext = v->toQString(); DEBUG << "parsing source = " << jtext; @@ -895,19 +894,17 @@ ReturnedValue JsonObject::method_parse(CallContext *ctx) ScopedValue result(scope, parser.parse(&error)); if (error.error != QJsonParseError::NoError) { DEBUG << "parse error" << error.errorString(); - return ctx->engine()->throwSyntaxError(QStringLiteral("JSON.parse: Parse error")); + RETURN_RESULT(scope.engine->throwSyntaxError(QStringLiteral("JSON.parse: Parse error"))); } - return result->asReturnedValue(); + scope.result = result; } -ReturnedValue JsonObject::method_stringify(CallContext *ctx) +void JsonObject::method_stringify(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Stringify stringify(scope.engine); - ScopedObject o(scope, ctx->argument(1)); + ScopedObject o(scope, callData->argument(1)); if (o) { stringify.replacerFunction = o->as(); if (o->isArrayObject()) { @@ -932,7 +929,7 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx) } } - ScopedValue s(scope, ctx->argument(2)); + ScopedValue s(scope, callData->argument(2)); if (NumberObject *n = s->as()) s = Encode(n->value()); else if (StringObject *so = s->as()) @@ -945,11 +942,11 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx) } - ScopedValue arg0(scope, ctx->argument(0)); + ScopedValue arg0(scope, callData->argument(0)); QString result = stringify.Str(QString(), arg0); if (result.isEmpty() || scope.engine->hasException) - return Encode::undefined(); - return ctx->d()->engine->newString(result)->asReturnedValue(); + RETURN_UNDEFINED(); + scope.result = scope.engine->newString(result); } diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h index 43248a214d..a73ce1c74e 100644 --- a/src/qml/jsruntime/qv4jsonobject_p.h +++ b/src/qml/jsruntime/qv4jsonobject_p.h @@ -88,8 +88,8 @@ private: typedef QSet V4ObjectSet; public: - static ReturnedValue method_parse(CallContext *ctx); - static ReturnedValue method_stringify(CallContext *ctx); + static void method_parse(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_stringify(const BuiltinFunction *, Scope &scope, CallData *callData); static ReturnedValue fromJsonValue(ExecutionEngine *engine, const QJsonValue &value); static ReturnedValue fromJsonObject(ExecutionEngine *engine, const QJsonObject &object); diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 41d8010fef..40682aaa4b 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -349,34 +349,33 @@ void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor) defineDefaultProperty(QStringLiteral("compile"), method_compile, 2); } -ReturnedValue RegExpPrototype::method_exec(CallContext *ctx) +void RegExpPrototype::method_exec(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - ScopedValue arg(scope, ctx->argument(0)); + ScopedValue arg(scope, callData->argument(0)); ScopedString str(scope, arg->toString(scope.engine)); if (scope.hasException()) - return Encode::undefined(); + RETURN_UNDEFINED(); QString s = str->toQString(); int offset = r->global() ? r->lastIndexProperty()->toInt32() : 0; if (offset < 0 || offset > s.length()) { *r->lastIndexProperty() = Primitive::fromInt32(0); - return Encode::null(); + RETURN_RESULT(Encode::null()); } uint* matchOffsets = (uint*)alloca(r->value()->captureCount() * 2 * sizeof(uint)); const int result = Scoped(scope, r->value())->match(s, offset, matchOffsets); - Scoped regExpCtor(scope, ctx->d()->engine->regExpCtor()); + Scoped regExpCtor(scope, scope.engine->regExpCtor()); regExpCtor->d()->clearLastMatch(); if (result == -1) { *r->lastIndexProperty() = Primitive::fromInt32(0); - return Encode::null(); + RETURN_RESULT(Encode::null()); } // fill in result data @@ -387,7 +386,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx) for (int i = 0; i < len; ++i) { int start = matchOffsets[i * 2]; int end = matchOffsets[i * 2 + 1]; - v = (start != -1) ? ctx->d()->engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined(); + v = (start != -1) ? scope.engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined(); array->arrayPut(i, v); } array->setArrayLengthUnchecked(len); @@ -403,84 +402,75 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx) if (r->global()) *r->lastIndexProperty() = Primitive::fromInt32(matchOffsets[1]); - return array.asReturnedValue(); + scope.result = array; } -ReturnedValue RegExpPrototype::method_test(CallContext *ctx) +void RegExpPrototype::method_test(const BuiltinFunction *b, Scope &scope, CallData *callData) { - Scope scope(ctx); - ScopedValue r(scope, method_exec(ctx)); - return Encode(!r->isNull()); + method_exec(b, scope, callData); + scope.result = Encode(!scope.result.isNull()); } -ReturnedValue RegExpPrototype::method_toString(CallContext *ctx) +void RegExpPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - return ctx->d()->engine->newString(r->toString())->asReturnedValue(); + scope.result = scope.engine->newString(r->toString()); } -ReturnedValue RegExpPrototype::method_compile(CallContext *ctx) +void RegExpPrototype::method_compile(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - ScopedCallData callData(scope, ctx->argc()); - memcpy(callData->args, ctx->args(), ctx->argc()*sizeof(Value)); + ScopedCallData cData(scope, callData->argc); + memcpy(cData->args, callData->args, callData->argc*sizeof(Value)); - ctx->d()->engine->regExpCtor()->as()->construct(scope, callData); + scope.engine->regExpCtor()->as()->construct(scope, cData); Scoped re(scope, scope.result.asReturnedValue()); r->d()->value = re->value(); r->d()->global = re->global(); - return Encode::undefined(); + RETURN_UNDEFINED(); } template -ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx) +void RegExpPrototype::method_get_lastMatch_n(const BuiltinFunction *, Scope &scope, CallData *) { - Scope scope(ctx); - ScopedArrayObject lastMatch(scope, static_cast(ctx->d()->engine->regExpCtor())->lastMatch()); - ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined()); - if (result->isUndefined()) - return ctx->d()->engine->newString()->asReturnedValue(); - return result->asReturnedValue(); + ScopedArrayObject lastMatch(scope, static_cast(scope.engine->regExpCtor())->lastMatch()); + scope.result = lastMatch ? lastMatch->getIndexed(index) : Encode::undefined(); + if (scope.result.isUndefined()) + scope.result = scope.engine->newString(); } -ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx) +void RegExpPrototype::method_get_lastParen(const BuiltinFunction *, Scope &scope, CallData *) { - Scope scope(ctx); - ScopedArrayObject lastMatch(scope, static_cast(ctx->d()->engine->regExpCtor())->lastMatch()); - ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined()); - if (result->isUndefined()) - return ctx->d()->engine->newString()->asReturnedValue(); - return result->asReturnedValue(); + ScopedArrayObject lastMatch(scope, static_cast(scope.engine->regExpCtor())->lastMatch()); + scope.result = lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined(); + if (scope.result.isUndefined()) + scope.result = scope.engine->newString(); } -ReturnedValue RegExpPrototype::method_get_input(CallContext *ctx) +void RegExpPrototype::method_get_input(const BuiltinFunction *, Scope &scope, CallData *) { - return static_cast(ctx->d()->engine->regExpCtor())->lastInput()->asReturnedValue(); + scope.result = static_cast(scope.engine->regExpCtor())->lastInput(); } -ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx) +void RegExpPrototype::method_get_leftContext(const BuiltinFunction *, Scope &scope, CallData *) { - Scope scope(ctx); - Scoped regExpCtor(scope, ctx->d()->engine->regExpCtor()); + Scoped regExpCtor(scope, scope.engine->regExpCtor()); QString lastInput = regExpCtor->lastInput()->toQString(); - return ctx->d()->engine->newString(lastInput.left(regExpCtor->lastMatchStart()))->asReturnedValue(); + scope.result = scope.engine->newString(lastInput.left(regExpCtor->lastMatchStart())); } -ReturnedValue RegExpPrototype::method_get_rightContext(CallContext *ctx) +void RegExpPrototype::method_get_rightContext(const BuiltinFunction *, Scope &scope, CallData *) { - Scope scope(ctx); - Scoped regExpCtor(scope, ctx->d()->engine->regExpCtor()); + Scoped regExpCtor(scope, scope.engine->regExpCtor()); QString lastInput = regExpCtor->lastInput()->toQString(); - return ctx->d()->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd()))->asReturnedValue(); + scope.result = scope.engine->newString(lastInput.mid(regExpCtor->lastMatchEnd())); } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h index 2c82cfdfd1..c0c7dfa78a 100644 --- a/src/qml/jsruntime/qv4regexpobject_p.h +++ b/src/qml/jsruntime/qv4regexpobject_p.h @@ -149,17 +149,17 @@ struct RegExpPrototype: RegExpObject { void init(ExecutionEngine *engine, Object *ctor); - static ReturnedValue method_exec(CallContext *ctx); - static ReturnedValue method_test(CallContext *ctx); - static ReturnedValue method_toString(CallContext *ctx); - static ReturnedValue method_compile(CallContext *ctx); + static void method_exec(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_test(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_compile(const BuiltinFunction *, Scope &scope, CallData *callData); template - static ReturnedValue method_get_lastMatch_n(CallContext *ctx); - static ReturnedValue method_get_lastParen(CallContext *ctx); - static ReturnedValue method_get_input(CallContext *ctx); - static ReturnedValue method_get_leftContext(CallContext *ctx); - static ReturnedValue method_get_rightContext(CallContext *ctx); + static void method_get_lastMatch_n(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_get_lastParen(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_get_input(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_get_leftContext(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_get_rightContext(const BuiltinFunction *, Scope &scope, CallData *callData); }; } diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 379c3babda..6cdc6200e7 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -71,14 +71,14 @@ struct ScopedValue; #define CHECK_EXCEPTION() \ do { \ if (scope.hasException()) { \ - scope.result = Encode::undefined(); \ + scope.result = QV4::Encode::undefined(); \ return; \ } \ } while (false) #define RETURN_UNDEFINED() \ do { \ - scope.result = Encode::undefined(); \ + scope.result = QV4::Encode::undefined(); \ return; \ } while (false) -- cgit v1.2.3 From 381e3151aea83806fb5bea2407fef67de3cc5014 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 5 Jan 2017 15:55:23 +0100 Subject: Convert builtins in MathObject to the new calling convention Change-Id: I631515893c35213f46fbee2a5f053ccdcb03af31 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4mathobject.cpp | 186 ++++++++++++++++++------------------ src/qml/jsruntime/qv4mathobject_p.h | 38 ++++---- 2 files changed, 112 insertions(+), 112 deletions(-) diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp index e03b2762cc..2d9d81c64b 100644 --- a/src/qml/jsruntime/qv4mathobject.cpp +++ b/src/qml/jsruntime/qv4mathobject.cpp @@ -92,160 +92,160 @@ static Q_ALWAYS_INLINE double copySign(double x, double y) return ::copysign(x, y); } -ReturnedValue MathObject::method_abs(CallContext *context) +void MathObject::method_abs(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (!context->argc()) - return Encode(qt_qnan()); + if (!callData->argc) + RETURN_RESULT(Encode(qt_qnan())); - if (context->args()[0].isInteger()) { - int i = context->args()[0].integerValue(); - return Encode(i < 0 ? - i : i); + if (callData->args[0].isInteger()) { + int i = callData->args[0].integerValue(); + RETURN_RESULT(Encode(i < 0 ? - i : i)); } - double v = context->args()[0].toNumber(); + double v = callData->args[0].toNumber(); if (v == 0) // 0 | -0 - return Encode(0); + RETURN_RESULT(Encode(0)); - return Encode(v < 0 ? -v : v); + RETURN_RESULT(Encode(v < 0 ? -v : v)); } -ReturnedValue MathObject::method_acos(CallContext *context) +void MathObject::method_acos(const BuiltinFunction *, Scope &scope, CallData *callData) { - double v = context->argc() ? context->args()[0].toNumber() : 2; + double v = callData->argc ? callData->args[0].toNumber() : 2; if (v > 1) - return Encode(qt_qnan()); + RETURN_RESULT(Encode(qt_qnan())); - return Encode(std::acos(v)); + RETURN_RESULT(Encode(std::acos(v))); } -ReturnedValue MathObject::method_asin(CallContext *context) +void MathObject::method_asin(const BuiltinFunction *, Scope &scope, CallData *callData) { - double v = context->argc() ? context->args()[0].toNumber() : 2; + double v = callData->argc ? callData->args[0].toNumber() : 2; if (v > 1) - return Encode(qt_qnan()); + RETURN_RESULT(Encode(qt_qnan())); else - return Encode(std::asin(v)); + RETURN_RESULT(Encode(std::asin(v))); } -ReturnedValue MathObject::method_atan(CallContext *context) +void MathObject::method_atan(const BuiltinFunction *, Scope &scope, CallData *callData) { - double v = context->argc() ? context->args()[0].toNumber() : qt_qnan(); + double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); if (v == 0.0) - return Encode(v); + RETURN_RESULT(Encode(v)); else - return Encode(std::atan(v)); + RETURN_RESULT(Encode(std::atan(v))); } -ReturnedValue MathObject::method_atan2(CallContext *context) +void MathObject::method_atan2(const BuiltinFunction *, Scope &scope, CallData *callData) { - double v1 = context->argc() ? context->args()[0].toNumber() : qt_qnan(); - double v2 = context->argc() > 1 ? context->args()[1].toNumber() : qt_qnan(); + double v1 = callData->argc ? callData->args[0].toNumber() : qt_qnan(); + double v2 = callData->argc > 1 ? callData->args[1].toNumber() : qt_qnan(); if ((v1 < 0) && qt_is_finite(v1) && qt_is_inf(v2) && (copySign(1.0, v2) == 1.0)) - return Encode(copySign(0, -1.0)); + RETURN_RESULT(Encode(copySign(0, -1.0))); if ((v1 == 0.0) && (v2 == 0.0)) { if ((copySign(1.0, v1) == 1.0) && (copySign(1.0, v2) == -1.0)) { - return Encode(M_PI); + RETURN_RESULT(Encode(M_PI)); } else if ((copySign(1.0, v1) == -1.0) && (copySign(1.0, v2) == -1.0)) { - return Encode(-M_PI); + RETURN_RESULT(Encode(-M_PI)); } } - return Encode(std::atan2(v1, v2)); + RETURN_RESULT(Encode(std::atan2(v1, v2))); } -ReturnedValue MathObject::method_ceil(CallContext *context) +void MathObject::method_ceil(const BuiltinFunction *, Scope &scope, CallData *callData) { - double v = context->argc() ? context->args()[0].toNumber() : qt_qnan(); + double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); if (v < 0.0 && v > -1.0) - return Encode(copySign(0, -1.0)); + RETURN_RESULT(Encode(copySign(0, -1.0))); else - return Encode(std::ceil(v)); + RETURN_RESULT(Encode(std::ceil(v))); } -ReturnedValue MathObject::method_cos(CallContext *context) +void MathObject::method_cos(const BuiltinFunction *, Scope &scope, CallData *callData) { - double v = context->argc() ? context->args()[0].toNumber() : qt_qnan(); - return Encode(std::cos(v)); + double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); + RETURN_RESULT(Encode(std::cos(v))); } -ReturnedValue MathObject::method_exp(CallContext *context) +void MathObject::method_exp(const BuiltinFunction *, Scope &scope, CallData *callData) { - double v = context->argc() ? context->args()[0].toNumber() : qt_qnan(); + double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); if (qt_is_inf(v)) { if (copySign(1.0, v) == -1.0) - return Encode(0); + RETURN_RESULT(Encode(0)); else - return Encode(qt_inf()); + RETURN_RESULT(Encode(qt_inf())); } else { - return Encode(std::exp(v)); + RETURN_RESULT(Encode(std::exp(v))); } } -ReturnedValue MathObject::method_floor(CallContext *context) +void MathObject::method_floor(const BuiltinFunction *, Scope &scope, CallData *callData) { - double v = context->argc() ? context->args()[0].toNumber() : qt_qnan(); - return Encode(std::floor(v)); + double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); + RETURN_RESULT(Encode(std::floor(v))); } -ReturnedValue MathObject::method_log(CallContext *context) +void MathObject::method_log(const BuiltinFunction *, Scope &scope, CallData *callData) { - double v = context->argc() ? context->args()[0].toNumber() : qt_qnan(); + double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); if (v < 0) - return Encode(qt_qnan()); + RETURN_RESULT(Encode(qt_qnan())); else - return Encode(std::log(v)); + RETURN_RESULT(Encode(std::log(v))); } -ReturnedValue MathObject::method_max(CallContext *context) +void MathObject::method_max(const BuiltinFunction *, Scope &scope, CallData *callData) { double mx = -qt_inf(); - for (int i = 0; i < context->argc(); ++i) { - double x = context->args()[i].toNumber(); + for (int i = 0; i < callData->argc; ++i) { + double x = callData->args[i].toNumber(); if (x > mx || std::isnan(x)) mx = x; } - return Encode(mx); + RETURN_RESULT(Encode(mx)); } -ReturnedValue MathObject::method_min(CallContext *context) +void MathObject::method_min(const BuiltinFunction *, Scope &scope, CallData *callData) { double mx = qt_inf(); - for (int i = 0; i < context->argc(); ++i) { - double x = context->args()[i].toNumber(); + for (int i = 0; i < callData->argc; ++i) { + double x = callData->args[i].toNumber(); if ((x == 0 && mx == x && copySign(1.0, x) == -1.0) || (x < mx) || std::isnan(x)) { mx = x; } } - return Encode(mx); + RETURN_RESULT(Encode(mx)); } -ReturnedValue MathObject::method_pow(CallContext *context) +void MathObject::method_pow(const BuiltinFunction *, Scope &scope, CallData *callData) { - double x = context->argc() > 0 ? context->args()[0].toNumber() : qt_qnan(); - double y = context->argc() > 1 ? context->args()[1].toNumber() : qt_qnan(); + double x = callData->argc > 0 ? callData->args[0].toNumber() : qt_qnan(); + double y = callData->argc > 1 ? callData->args[1].toNumber() : qt_qnan(); if (std::isnan(y)) - return Encode(qt_qnan()); + RETURN_RESULT(Encode(qt_qnan())); if (y == 0) { - return Encode(1); + RETURN_RESULT(Encode(1)); } else if (((x == 1) || (x == -1)) && std::isinf(y)) { - return Encode(qt_qnan()); + RETURN_RESULT(Encode(qt_qnan())); } else if (((x == 0) && copySign(1.0, x) == 1.0) && (y < 0)) { - return Encode(qInf()); + RETURN_RESULT(Encode(qInf())); } else if ((x == 0) && copySign(1.0, x) == -1.0) { if (y < 0) { if (std::fmod(-y, 2.0) == 1.0) - return Encode(-qt_inf()); + RETURN_RESULT(Encode(-qt_inf())); else - return Encode(qt_inf()); + RETURN_RESULT(Encode(qt_inf())); } else if (y > 0) { if (std::fmod(y, 2.0) == 1.0) - return Encode(copySign(0, -1.0)); + RETURN_RESULT(Encode(copySign(0, -1.0))); else - return Encode(0); + RETURN_RESULT(Encode(0)); } } @@ -253,78 +253,78 @@ ReturnedValue MathObject::method_pow(CallContext *context) else if (qt_is_inf(x) && copySign(1.0, x) == -1.0) { if (y > 0) { if (std::fmod(y, 2.0) == 1.0) - return Encode(-qt_inf()); + RETURN_RESULT(Encode(-qt_inf())); else - return Encode(qt_inf()); + RETURN_RESULT(Encode(qt_inf())); } else if (y < 0) { if (std::fmod(-y, 2.0) == 1.0) - return Encode(copySign(0, -1.0)); + RETURN_RESULT(Encode(copySign(0, -1.0))); else - return Encode(0); + RETURN_RESULT(Encode(0)); } } #endif else { - return Encode(std::pow(x, y)); + RETURN_RESULT(Encode(std::pow(x, y))); } // ### - return Encode(qt_qnan()); + RETURN_RESULT(Encode(qt_qnan())); } Q_GLOBAL_STATIC(QThreadStorage, seedCreatedStorage); -ReturnedValue MathObject::method_random(CallContext *context) +void MathObject::method_random(const BuiltinFunction *, Scope &scope, CallData *) { if (!seedCreatedStorage()->hasLocalData()) { int msecs = QTime(0,0,0).msecsTo(QTime::currentTime()); Q_ASSERT(msecs >= 0); - qsrand(uint(uint(msecs) ^ reinterpret_cast(context))); + qsrand(uint(uint(msecs) ^ reinterpret_cast(scope.engine))); seedCreatedStorage()->setLocalData(new bool(true)); } // rand()/qrand() return a value where the upperbound is RAND_MAX inclusive. So, instead of // dividing by RAND_MAX (which would return 0..RAND_MAX inclusive), we divide by RAND_MAX + 1. qint64 upperLimit = qint64(RAND_MAX) + 1; - return Encode(qrand() / double(upperLimit)); + RETURN_RESULT(Encode(qrand() / double(upperLimit))); } -ReturnedValue MathObject::method_round(CallContext *context) +void MathObject::method_round(const BuiltinFunction *, Scope &scope, CallData *callData) { - double v = context->argc() ? context->args()[0].toNumber() : qt_qnan(); + double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); v = copySign(std::floor(v + 0.5), v); - return Encode(v); + RETURN_RESULT(Encode(v)); } -ReturnedValue MathObject::method_sign(CallContext *context) +void MathObject::method_sign(const BuiltinFunction *, Scope &scope, CallData *callData) { - double v = context->argc() ? context->args()[0].toNumber() : qt_qnan(); + double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); if (std::isnan(v)) - return Encode(qt_qnan()); + RETURN_RESULT(Encode(qt_qnan())); if (qIsNull(v)) - return v; + RETURN_RESULT(Encode(v)); - return Encode(std::signbit(v) ? -1 : 1); + RETURN_RESULT(Encode(std::signbit(v) ? -1 : 1)); } -ReturnedValue MathObject::method_sin(CallContext *context) +void MathObject::method_sin(const BuiltinFunction *, Scope &scope, CallData *callData) { - double v = context->argc() ? context->args()[0].toNumber() : qt_qnan(); - return Encode(std::sin(v)); + double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); + RETURN_RESULT(Encode(std::sin(v))); } -ReturnedValue MathObject::method_sqrt(CallContext *context) +void MathObject::method_sqrt(const BuiltinFunction *, Scope &scope, CallData *callData) { - double v = context->argc() ? context->args()[0].toNumber() : qt_qnan(); - return Encode(std::sqrt(v)); + double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); + RETURN_RESULT(Encode(std::sqrt(v))); } -ReturnedValue MathObject::method_tan(CallContext *context) +void MathObject::method_tan(const BuiltinFunction *, Scope &scope, CallData *callData) { - double v = context->argc() ? context->args()[0].toNumber() : qt_qnan(); + double v = callData->argc ? callData->args[0].toNumber() : qt_qnan(); if (v == 0.0) - return Encode(v); + RETURN_RESULT(Encode(v)); else - return Encode(std::tan(v)); + RETURN_RESULT(Encode(std::tan(v))); } diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h index f6b1a4395f..e617712905 100644 --- a/src/qml/jsruntime/qv4mathobject_p.h +++ b/src/qml/jsruntime/qv4mathobject_p.h @@ -69,25 +69,25 @@ struct MathObject: Object V4_OBJECT2(MathObject, Object) Q_MANAGED_TYPE(MathObject) - static ReturnedValue method_abs(CallContext *context); - static ReturnedValue method_acos(CallContext *context); - static ReturnedValue method_asin(CallContext *context); - static ReturnedValue method_atan(CallContext *context); - static ReturnedValue method_atan2(CallContext *context); - static ReturnedValue method_ceil(CallContext *context); - static ReturnedValue method_cos(CallContext *context); - static ReturnedValue method_exp(CallContext *context); - static ReturnedValue method_floor(CallContext *context); - static ReturnedValue method_log(CallContext *context); - static ReturnedValue method_max(CallContext *context); - static ReturnedValue method_min(CallContext *context); - static ReturnedValue method_pow(CallContext *context); - static ReturnedValue method_random(CallContext *context); - static ReturnedValue method_round(CallContext *context); - static ReturnedValue method_sign(CallContext *context); - static ReturnedValue method_sin(CallContext *context); - static ReturnedValue method_sqrt(CallContext *context); - static ReturnedValue method_tan(CallContext *context); + static void method_abs(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_acos(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_asin(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_atan(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_atan2(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_ceil(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_cos(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_exp(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_floor(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_log(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_max(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_min(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_pow(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_random(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_round(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_sign(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_sin(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_sqrt(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_tan(const BuiltinFunction *, Scope &scope, CallData *callData); }; } -- cgit v1.2.3 From 25552c1404dff66ae9681e57f2b9a8be08d3828a Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 5 Jan 2017 22:21:35 +0100 Subject: Convert more builtin functions to the new calling convention Change-Id: I053215261e1186aff25f29e0967219ef667f7678 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4qobjectwrapper.cpp | 65 ++--- src/qml/jsruntime/qv4qobjectwrapper_p.h | 4 +- src/qml/jsruntime/qv4scopedvalue_p.h | 6 + src/qml/jsruntime/qv4sequenceobject.cpp | 64 ++--- src/qml/jsruntime/qv4sequenceobject_p.h | 6 +- src/qml/jsruntime/qv4variantobject.cpp | 47 +-- src/qml/jsruntime/qv4variantobject_p.h | 8 +- src/qml/qml/qqmlcomponent.cpp | 59 ++-- src/qml/qml/qqmlvaluetypewrapper.cpp | 12 +- src/qml/qml/qqmlvaluetypewrapper_p.h | 2 +- src/qml/qml/qqmlxmlhttprequest.cpp | 496 +++++++++++++++----------------- src/qml/qml/v8/qv4domerrors_p.h | 8 + src/qml/types/qqmldelegatemodel.cpp | 79 ++--- src/qml/types/qqmldelegatemodel_p_p.h | 6 +- src/qml/types/qquickworkerscript.cpp | 13 +- 15 files changed, 424 insertions(+), 451 deletions(-) diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 77dbb18b50..7260e71fab 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -826,40 +826,39 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase } // namespace QV4 -ReturnedValue QObjectWrapper::method_connect(CallContext *ctx) +void QObjectWrapper::method_connect(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() == 0) - V4THROW_ERROR("Function.prototype.connect: no arguments given"); + if (callData->argc == 0) + THROW_GENERIC_ERROR("Function.prototype.connect: no arguments given"); - QPair signalInfo = extractQtSignal(ctx->thisObject()); + QPair signalInfo = extractQtSignal(callData->thisObject); QObject *signalObject = signalInfo.first; int signalIndex = signalInfo.second; // in method range, not signal range! if (signalIndex < 0) - V4THROW_ERROR("Function.prototype.connect: this object is not a signal"); + THROW_GENERIC_ERROR("Function.prototype.connect: this object is not a signal"); if (!signalObject) - V4THROW_ERROR("Function.prototype.connect: cannot connect to deleted QObject"); + THROW_GENERIC_ERROR("Function.prototype.connect: cannot connect to deleted QObject"); if (signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal) - V4THROW_ERROR("Function.prototype.connect: this object is not a signal"); + THROW_GENERIC_ERROR("Function.prototype.connect: this object is not a signal"); - QV4::Scope scope(ctx); QV4::ScopedFunctionObject f(scope); QV4::ScopedValue thisObject (scope, QV4::Encode::undefined()); - if (ctx->argc() == 1) { - f = ctx->args()[0]; - } else if (ctx->argc() >= 2) { - thisObject = ctx->args()[0]; - f = ctx->args()[1]; + if (callData->argc == 1) { + f = callData->args[0]; + } else if (callData->argc >= 2) { + thisObject = callData->args[0]; + f = callData->args[1]; } if (!f) - V4THROW_ERROR("Function.prototype.connect: target is not a function"); + THROW_GENERIC_ERROR("Function.prototype.connect: target is not a function"); if (!thisObject->isUndefined() && !thisObject->isObject()) - V4THROW_ERROR("Function.prototype.connect: target this is not an object"); + THROW_GENERIC_ERROR("Function.prototype.connect: target this is not an object"); QV4::QObjectSlotDispatcher *slot = new QV4::QObjectSlotDispatcher; slot->signalIndex = signalIndex; @@ -874,49 +873,47 @@ ReturnedValue QObjectWrapper::method_connect(CallContext *ctx) } QObjectPrivate::connect(signalObject, signalIndex, slot, Qt::AutoConnection); - return Encode::undefined(); + RETURN_UNDEFINED(); } -ReturnedValue QObjectWrapper::method_disconnect(CallContext *ctx) +void QObjectWrapper::method_disconnect(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() == 0) - V4THROW_ERROR("Function.prototype.disconnect: no arguments given"); - - QV4::Scope scope(ctx); + if (callData->argc == 0) + THROW_GENERIC_ERROR("Function.prototype.disconnect: no arguments given"); - QPair signalInfo = extractQtSignal(ctx->thisObject()); + QPair signalInfo = extractQtSignal(callData->thisObject); QObject *signalObject = signalInfo.first; int signalIndex = signalInfo.second; if (signalIndex == -1) - V4THROW_ERROR("Function.prototype.disconnect: this object is not a signal"); + THROW_GENERIC_ERROR("Function.prototype.disconnect: this object is not a signal"); if (!signalObject) - V4THROW_ERROR("Function.prototype.disconnect: cannot disconnect from deleted QObject"); + THROW_GENERIC_ERROR("Function.prototype.disconnect: cannot disconnect from deleted QObject"); if (signalIndex < 0 || signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal) - V4THROW_ERROR("Function.prototype.disconnect: this object is not a signal"); + THROW_GENERIC_ERROR("Function.prototype.disconnect: this object is not a signal"); QV4::ScopedFunctionObject functionValue(scope); QV4::ScopedValue functionThisValue(scope, QV4::Encode::undefined()); - if (ctx->argc() == 1) { - functionValue = ctx->args()[0]; - } else if (ctx->argc() >= 2) { - functionThisValue = ctx->args()[0]; - functionValue = ctx->args()[1]; + if (callData->argc == 1) { + functionValue = callData->args[0]; + } else if (callData->argc >= 2) { + functionThisValue = callData->args[0]; + functionValue = callData->args[1]; } if (!functionValue) - V4THROW_ERROR("Function.prototype.disconnect: target is not a function"); + THROW_GENERIC_ERROR("Function.prototype.disconnect: target is not a function"); if (!functionThisValue->isUndefined() && !functionThisValue->isObject()) - V4THROW_ERROR("Function.prototype.disconnect: target this is not an object"); + THROW_GENERIC_ERROR("Function.prototype.disconnect: target this is not an object"); QPair functionData = QObjectMethod::extractQtMethod(functionValue); void *a[] = { - ctx->d()->engine, + scope.engine, functionValue.ptr, functionThisValue.ptr, functionData.first, @@ -925,7 +922,7 @@ ReturnedValue QObjectWrapper::method_disconnect(CallContext *ctx) QObjectPrivate::disconnect(signalObject, signalIndex, reinterpret_cast(&a)); - return Encode::undefined(); + RETURN_UNDEFINED(); } static void markChildQObjectsRecursively(QObject *parent, QV4::ExecutionEngine *e) diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index c7c4f4dd77..b09e06cec5 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -197,8 +197,8 @@ protected: static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes); static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e); - static ReturnedValue method_connect(CallContext *ctx); - static ReturnedValue method_disconnect(CallContext *ctx); + static void method_connect(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_disconnect(const BuiltinFunction *, Scope &scope, CallData *callData); private: Q_NEVER_INLINE static ReturnedValue wrap_slowPath(ExecutionEngine *engine, QObject *object); diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 6cdc6200e7..6775028272 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -94,6 +94,12 @@ struct ScopedValue; return; \ } while (false) +#define THROW_GENERIC_ERROR(str) \ + do { \ + scope.result = scope.engine->throwError(QString::fromUtf8(str)); \ + return; \ + } while (false) + struct Scope { inline Scope(ExecutionContext *ctx) : engine(ctx->d()->engine) diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 58da7b9f68..8ce10e326d 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -404,28 +404,28 @@ public: struct CompareFunctor { - CompareFunctor(QV4::ExecutionContext *ctx, const QV4::Value &compareFn) - : m_ctx(ctx), m_compareFn(&compareFn) + CompareFunctor(QV4::ExecutionEngine *v4, const QV4::Value &compareFn) + : m_v4(v4), m_compareFn(&compareFn) {} bool operator()(typename Container::value_type lhs, typename Container::value_type rhs) { - QV4::Scope scope(m_ctx); + QV4::Scope scope(m_v4); ScopedObject compare(scope, m_compareFn); ScopedCallData callData(scope, 2); - callData->args[0] = convertElementToValue(this->m_ctx->d()->engine, lhs); - callData->args[1] = convertElementToValue(this->m_ctx->d()->engine, rhs); - callData->thisObject = this->m_ctx->d()->engine->globalObject; + callData->args[0] = convertElementToValue(m_v4, lhs); + callData->args[1] = convertElementToValue(m_v4, rhs); + callData->thisObject = m_v4->globalObject; compare->call(scope, callData); return scope.result.toNumber() < 0; } private: - QV4::ExecutionContext *m_ctx; + QV4::ExecutionEngine *m_v4; const QV4::Value *m_compareFn; }; - void sort(QV4::CallContext *ctx) + void sort(const BuiltinFunction *, Scope &scope, CallData *callData) { if (d()->isReference) { if (!d()->object) @@ -433,9 +433,8 @@ public: loadReference(); } - QV4::Scope scope(ctx); - if (ctx->argc() == 1 && ctx->args()[0].as()) { - CompareFunctor cf(ctx, ctx->args()[0]); + if (callData->argc == 1 && callData->args[0].as()) { + CompareFunctor cf(scope.engine, callData->args[0]); std::sort(d()->container->begin(), d()->container->end(), cf); } else { DefaultCompareFunctor cf; @@ -446,45 +445,43 @@ public: storeReference(); } - static QV4::ReturnedValue method_get_length(QV4::CallContext *ctx) + static void method_get_length(const BuiltinFunction *, Scope &scope, CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped > This(scope, ctx->thisObject().as >()); + QV4::Scoped > This(scope, callData->thisObject.as >()); if (!This) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); if (This->d()->isReference) { if (!This->d()->object) - return QV4::Encode(0); + RETURN_RESULT(Encode(0)); This->loadReference(); } - return QV4::Encode(This->d()->container->count()); + RETURN_RESULT(Encode(This->d()->container->count())); } - static QV4::ReturnedValue method_set_length(QV4::CallContext* ctx) + static void method_set_length(const BuiltinFunction *, Scope &scope, CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped > This(scope, ctx->thisObject().as >()); + QV4::Scoped > This(scope, callData->thisObject.as >()); if (!This) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - quint32 newLength = ctx->args()[0].toUInt32(); + quint32 newLength = callData->args[0].toUInt32(); /* Qt containers have int (rather than uint) allowable indexes. */ if (newLength > INT_MAX) { generateWarning(scope.engine, QLatin1String("Index out of range during length set")); - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } /* Read the sequence from the QObject property if we're a reference */ if (This->d()->isReference) { if (!This->d()->object) - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); This->loadReference(); } /* Determine whether we need to modify the sequence */ qint32 newCount = static_cast(newLength); qint32 count = This->d()->container->count(); if (newCount == count) { - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } else if (newCount > count) { /* according to ECMA262r3 we need to insert */ /* undefined values increasing length to newLength. */ @@ -506,7 +503,7 @@ public: /* write back. already checked that object is non-null, so skip that check here. */ This->storeReference(); } - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } QVariant toVariant() const @@ -625,26 +622,25 @@ void SequencePrototype::init() } #undef REGISTER_QML_SEQUENCE_METATYPE -QV4::ReturnedValue SequencePrototype::method_sort(QV4::CallContext *ctx) +void SequencePrototype::method_sort(const BuiltinFunction *b, Scope &scope, CallData *callData) { - QV4::Scope scope(ctx); - QV4::ScopedObject o(scope, ctx->thisObject()); + QV4::ScopedObject o(scope, callData->thisObject); if (!o || !o->isListType()) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - if (ctx->argc() >= 2) - return o.asReturnedValue(); + if (callData->argc >= 2) + RETURN_RESULT(o); #define CALL_SORT(SequenceElementType, SequenceElementTypeName, SequenceType, DefaultValue) \ if (QQml##SequenceElementTypeName##List *s = o->as()) { \ - s->sort(ctx); \ + s->sort(b, scope, callData); \ } else FOREACH_QML_SEQUENCE_TYPE(CALL_SORT) #undef CALL_SORT {} - return o.asReturnedValue(); + RETURN_RESULT(o); } #define IS_SEQUENCE(unused1, unused2, SequenceType, unused3) \ diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h index c0416ad639..6f96b9f760 100644 --- a/src/qml/jsruntime/qv4sequenceobject_p.h +++ b/src/qml/jsruntime/qv4sequenceobject_p.h @@ -67,12 +67,12 @@ struct SequencePrototype : public QV4::Object { void init(); - static ReturnedValue method_valueOf(QV4::CallContext *ctx) + static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData) { - return ctx->thisObject().toString(ctx->engine())->asReturnedValue(); + scope.result = callData->thisObject.toString(scope.engine); } - static ReturnedValue method_sort(QV4::CallContext *ctx); + static void method_sort(const BuiltinFunction *, Scope &scope, CallData *callData); static bool isSequenceType(int sequenceTypeId); static ReturnedValue newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded); diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp index 455a7ccb65..5cab4c5386 100644 --- a/src/qml/jsruntime/qv4variantobject.cpp +++ b/src/qml/jsruntime/qv4variantobject.cpp @@ -113,67 +113,68 @@ void VariantPrototype::init() defineDefaultProperty(engine()->id_toString(), method_toString, 0); } -QV4::ReturnedValue VariantPrototype::method_preserve(CallContext *ctx) +void VariantPrototype::method_preserve(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped o(scope, ctx->thisObject().as()); + Scoped o(scope, callData->thisObject.as()); if (o && o->d()->isScarce()) o->d()->addVmePropertyReference(); - return Encode::undefined(); + RETURN_UNDEFINED(); } -QV4::ReturnedValue VariantPrototype::method_destroy(CallContext *ctx) +void VariantPrototype::method_destroy(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped o(scope, ctx->thisObject().as()); + Scoped o(scope, callData->thisObject.as()); if (o) { if (o->d()->isScarce()) o->d()->addVmePropertyReference(); o->d()->data() = QVariant(); } - return Encode::undefined(); + RETURN_UNDEFINED(); } -QV4::ReturnedValue VariantPrototype::method_toString(CallContext *ctx) +void VariantPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped o(scope, ctx->thisObject().as()); + Scoped o(scope, callData->thisObject.as()); if (!o) - return Encode::undefined(); + RETURN_UNDEFINED(); QString result = o->d()->data().toString(); if (result.isEmpty() && !o->d()->data().canConvert(QVariant::String)) { result = QLatin1String("QVariant(") + QLatin1String(o->d()->data().typeName()) + QLatin1Char(')'); } - return Encode(ctx->d()->engine->newString(result)); + scope.result = scope.engine->newString(result); } -QV4::ReturnedValue VariantPrototype::method_valueOf(CallContext *ctx) +void VariantPrototype::method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - Scoped o(scope, ctx->thisObject().as()); + Scoped o(scope, callData->thisObject.as()); if (o) { QVariant v = o->d()->data(); switch (v.type()) { case QVariant::Invalid: - return Encode::undefined(); + scope.result = Encode::undefined(); + return; case QVariant::String: - return Encode(ctx->d()->engine->newString(v.toString())); + scope.result = scope.engine->newString(v.toString()); + return; case QVariant::Int: - return Encode(v.toInt()); + scope.result = Encode(v.toInt()); + return; case QVariant::Double: case QVariant::UInt: - return Encode(v.toDouble()); + scope.result = Encode(v.toDouble()); + return; case QVariant::Bool: - return Encode(v.toBool()); + scope.result = Encode(v.toBool()); + return; default: if (QMetaType::typeFlags(v.userType()) & QMetaType::IsEnumeration) - return Encode(v.toInt()); + RETURN_RESULT(Encode(v.toInt())); break; } } - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject; } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h index 9a04069c12..ef51b6632d 100644 --- a/src/qml/jsruntime/qv4variantobject_p.h +++ b/src/qml/jsruntime/qv4variantobject_p.h @@ -107,10 +107,10 @@ struct VariantPrototype : VariantObject public: void init(); - static ReturnedValue method_preserve(CallContext *ctx); - static ReturnedValue method_destroy(CallContext *ctx); - static ReturnedValue method_toString(CallContext *ctx); - static ReturnedValue method_valueOf(CallContext *ctx); + static void method_preserve(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_destroy(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_valueOf(const BuiltinFunction *, Scope &scope, CallData *callData); }; } diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 50ed58e63d..a04f47e6a4 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1063,11 +1063,11 @@ struct QmlIncubatorObject : public QV4::Object V4_OBJECT2(QmlIncubatorObject, Object) V4_NEEDS_DESTROY - static QV4::ReturnedValue method_get_statusChanged(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_statusChanged(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_status(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_object(QV4::CallContext *ctx); - static QV4::ReturnedValue method_forceCompletion(QV4::CallContext *ctx); + static void method_get_statusChanged(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_set_statusChanged(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_get_status(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_get_object(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_forceCompletion(const BuiltinFunction *, Scope &scope, CallData *callData); static void markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e); @@ -1415,58 +1415,53 @@ QQmlComponentExtension::QQmlComponentExtension(QV4::ExecutionEngine *v4) incubationProto.set(v4, proto); } -QV4::ReturnedValue QV4::QmlIncubatorObject::method_get_object(QV4::CallContext *ctx) +void QV4::QmlIncubatorObject::method_get_object(const BuiltinFunction *, Scope &scope, CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped o(scope, ctx->thisObject().as()); + QV4::Scoped o(scope, callData->thisObject.as()); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - return QV4::QObjectWrapper::wrap(ctx->d()->engine, o->d()->incubator->object()); + scope.result = QV4::QObjectWrapper::wrap(scope.engine, o->d()->incubator->object()); } -QV4::ReturnedValue QV4::QmlIncubatorObject::method_forceCompletion(QV4::CallContext *ctx) +void QV4::QmlIncubatorObject::method_forceCompletion(const BuiltinFunction *, Scope &scope, CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped o(scope, ctx->thisObject().as()); + QV4::Scoped o(scope, callData->thisObject.as()); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); o->d()->incubator->forceCompletion(); - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } -QV4::ReturnedValue QV4::QmlIncubatorObject::method_get_status(QV4::CallContext *ctx) +void QV4::QmlIncubatorObject::method_get_status(const BuiltinFunction *, Scope &scope, CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped o(scope, ctx->thisObject().as()); + QV4::Scoped o(scope, callData->thisObject.as()); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - return QV4::Encode(o->d()->incubator->status()); + scope.result = QV4::Encode(o->d()->incubator->status()); } -QV4::ReturnedValue QV4::QmlIncubatorObject::method_get_statusChanged(QV4::CallContext *ctx) +void QV4::QmlIncubatorObject::method_get_statusChanged(const BuiltinFunction *, Scope &scope, CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped o(scope, ctx->thisObject().as()); + QV4::Scoped o(scope, callData->thisObject.as()); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - return o->d()->statusChanged.asReturnedValue(); + scope.result = o->d()->statusChanged; } -QV4::ReturnedValue QV4::QmlIncubatorObject::method_set_statusChanged(QV4::CallContext *ctx) +void QV4::QmlIncubatorObject::method_set_statusChanged(const BuiltinFunction *, Scope &scope, CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped o(scope, ctx->thisObject().as()); - if (!o || ctx->argc() < 1) - return ctx->engine()->throwTypeError(); + QV4::Scoped o(scope, callData->thisObject.as()); + if (!o || callData->argc < 1) + THROW_TYPE_ERROR(); + o->d()->statusChanged = callData->args[0]; - o->d()->statusChanged = ctx->args()[0]; - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } QQmlComponentExtension::~QQmlComponentExtension() diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 6ce52bb9e5..44b612e7d2 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -312,18 +312,18 @@ bool QQmlValueTypeWrapper::write(QObject *target, int propertyIndex) const return true; } -ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx) +void QQmlValueTypeWrapper::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData) { - Object *o = ctx->thisObject().as(); + Object *o = callData->thisObject.as(); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); QQmlValueTypeWrapper *w = o->as(); if (!w) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); if (QQmlValueTypeReference *ref = w->as()) if (!ref->readReferenceValue()) - return Encode::undefined(); + RETURN_UNDEFINED(); QString result; // Prepare a buffer to pass to QMetaType::convert() @@ -346,7 +346,7 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx) } result += QLatin1Char(')'); } - return Encode(ctx->engine()->newString(result)); + scope.result = scope.engine->newString(result); } ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *hasProperty) diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h index fec54df770..87f9116056 100644 --- a/src/qml/qml/qqmlvaluetypewrapper_p.h +++ b/src/qml/qml/qqmlvaluetypewrapper_p.h @@ -111,7 +111,7 @@ public: static PropertyAttributes query(const Managed *, String *name); static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes); - static QV4::ReturnedValue method_toString(CallContext *ctx); + static void method_toString(const BuiltinFunction *, Scope &scope, CallData *callData); static void initProto(ExecutionEngine *v4); }; diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index 22c3c49c58..d0d9f080da 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -71,10 +71,12 @@ using namespace QV4; #if QT_CONFIG(xmlstreamreader) && QT_CONFIG(qml_network) -#define V4THROW_REFERENCE(string) { \ - ScopedObject error(scope, ctx->engine()->newReferenceErrorObject(QStringLiteral(string))); \ - return ctx->engine()->throwError(error); \ - } +#define V4THROW_REFERENCE(string) \ + do { \ + ScopedObject error(scope, scope.engine->newReferenceErrorObject(QStringLiteral(string))); \ + scope.result = scope.engine->throwError(error); \ + return; \ + } while (false) QT_BEGIN_NAMESPACE @@ -274,25 +276,25 @@ public: static void initClass(ExecutionEngine *engine); // JS API - static ReturnedValue method_get_nodeName(CallContext *ctx); - static ReturnedValue method_get_nodeValue(CallContext *ctx); - static ReturnedValue method_get_nodeType(CallContext *ctx); - static ReturnedValue method_get_namespaceUri(CallContext *ctx); - - static ReturnedValue method_get_parentNode(CallContext *ctx); - static ReturnedValue method_get_childNodes(CallContext *ctx); - static ReturnedValue method_get_firstChild(CallContext *ctx); - static ReturnedValue method_get_lastChild(CallContext *ctx); - static ReturnedValue method_get_previousSibling(CallContext *ctx); - static ReturnedValue method_get_nextSibling(CallContext *ctx); - static ReturnedValue method_get_attributes(CallContext *ctx); - - //static ReturnedValue ownerDocument(CallContext *ctx); - //static ReturnedValue namespaceURI(CallContext *ctx); - //static ReturnedValue prefix(CallContext *ctx); - //static ReturnedValue localName(CallContext *ctx); - //static ReturnedValue baseURI(CallContext *ctx); - //static ReturnedValue textContent(CallContext *ctx); + static void method_get_nodeName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_nodeValue(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_nodeType(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_namespaceUri(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + + static void method_get_parentNode(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_childNodes(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_firstChild(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_lastChild(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_previousSibling(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_nextSibling(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_attributes(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + + //static void ownerDocument(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + //static void namespaceURI(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + //static void prefix(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + //static void localName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + //static void baseURI(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + //static void textContent(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); static ReturnedValue getProto(ExecutionEngine *v4); @@ -353,12 +355,12 @@ class Attr : public Node { public: // JS API - static ReturnedValue method_name(CallContext *ctx); -// static ReturnedValue specified(CallContext *); - static ReturnedValue method_value(CallContext *ctx); - static ReturnedValue method_ownerElement(CallContext *ctx); -// static ReturnedValue schemaTypeInfo(CallContext *); -// static ReturnedValue isId(CallContext *c); + static void method_name(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); +// static void specified(CallContext *); + static void method_value(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_ownerElement(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); +// static void schemaTypeInfo(CallContext *); +// static void isId(CallContext *c); // C++ API static ReturnedValue prototype(ExecutionEngine *); @@ -368,7 +370,7 @@ class CharacterData : public Node { public: // JS API - static ReturnedValue method_length(CallContext *ctx); + static void method_length(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); // C++ API static ReturnedValue prototype(ExecutionEngine *v4); @@ -378,8 +380,8 @@ class Text : public CharacterData { public: // JS API - static ReturnedValue method_isElementContentWhitespace(CallContext *ctx); - static ReturnedValue method_wholeText(CallContext *ctx); + static void method_isElementContentWhitespace(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_wholeText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); // C++ API static ReturnedValue prototype(ExecutionEngine *); @@ -396,10 +398,10 @@ class Document : public Node { public: // JS API - static ReturnedValue method_xmlVersion(CallContext *ctx); - static ReturnedValue method_xmlEncoding(CallContext *ctx); - static ReturnedValue method_xmlStandalone(CallContext *ctx); - static ReturnedValue method_documentElement(CallContext *ctx); + static void method_xmlVersion(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_xmlEncoding(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_xmlStandalone(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_documentElement(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); // C++ API static ReturnedValue prototype(ExecutionEngine *); @@ -418,12 +420,11 @@ void NodeImpl::release() document->release(); } -ReturnedValue NodePrototype::method_get_nodeName(CallContext *ctx) +void NodePrototype::method_get_nodeName(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); QString name; switch (r->d()->d->type) { @@ -440,15 +441,14 @@ ReturnedValue NodePrototype::method_get_nodeName(CallContext *ctx) name = r->d()->d->name; break; } - return Encode(ctx->d()->engine->newString(name)); + scope.result = Encode(scope.engine->newString(name)); } -ReturnedValue NodePrototype::method_get_nodeValue(CallContext *ctx) +void NodePrototype::method_get_nodeValue(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); if (r->d()->d->type == NodeImpl::Document || r->d()->d->type == NodeImpl::DocumentFragment || @@ -457,135 +457,128 @@ ReturnedValue NodePrototype::method_get_nodeValue(CallContext *ctx) r->d()->d->type == NodeImpl::Entity || r->d()->d->type == NodeImpl::EntityReference || r->d()->d->type == NodeImpl::Notation) - return Encode::null(); + RETURN_RESULT(Encode::null()); - return Encode(ctx->d()->engine->newString(r->d()->d->data)); + scope.result = Encode(scope.engine->newString(r->d()->d->data)); } -ReturnedValue NodePrototype::method_get_nodeType(CallContext *ctx) +void NodePrototype::method_get_nodeType(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - return Encode(r->d()->d->type); + scope.result = Encode(r->d()->d->type); } -ReturnedValue NodePrototype::method_get_namespaceUri(CallContext *ctx) +void NodePrototype::method_get_namespaceUri(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - return Encode(ctx->d()->engine->newString(r->d()->d->namespaceUri)); + scope.result = Encode(scope.engine->newString(r->d()->d->namespaceUri)); } -ReturnedValue NodePrototype::method_get_parentNode(CallContext *ctx) +void NodePrototype::method_get_parentNode(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); if (r->d()->d->parent) - return Node::create(scope.engine, r->d()->d->parent); + scope.result = Node::create(scope.engine, r->d()->d->parent); else - return Encode::null(); + scope.result = Encode::null(); } -ReturnedValue NodePrototype::method_get_childNodes(CallContext *ctx) +void NodePrototype::method_get_childNodes(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); - return NodeList::create(scope.engine, r->d()->d); + scope.result = NodeList::create(scope.engine, r->d()->d); } -ReturnedValue NodePrototype::method_get_firstChild(CallContext *ctx) +void NodePrototype::method_get_firstChild(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); if (r->d()->d->children.isEmpty()) - return Encode::null(); + scope.result = Encode::null(); else - return Node::create(scope.engine, r->d()->d->children.constFirst()); + scope.result = Node::create(scope.engine, r->d()->d->children.constFirst()); } -ReturnedValue NodePrototype::method_get_lastChild(CallContext *ctx) +void NodePrototype::method_get_lastChild(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); if (r->d()->d->children.isEmpty()) - return Encode::null(); + scope.result = Encode::null(); else - return Node::create(scope.engine, r->d()->d->children.constLast()); + scope.result = Node::create(scope.engine, r->d()->d->children.constLast()); } -ReturnedValue NodePrototype::method_get_previousSibling(CallContext *ctx) +void NodePrototype::method_get_previousSibling(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); if (!r->d()->d->parent) - return Encode::null(); + RETURN_RESULT(Encode::null()); for (int ii = 0; ii < r->d()->d->parent->children.count(); ++ii) { if (r->d()->d->parent->children.at(ii) == r->d()->d) { if (ii == 0) - return Encode::null(); + scope.result = Encode::null(); else - return Node::create(scope.engine, r->d()->d->parent->children.at(ii - 1)); + scope.result = Node::create(scope.engine, r->d()->d->parent->children.at(ii - 1)); + return; } } - return Encode::null(); + scope.result = Encode::null(); } -ReturnedValue NodePrototype::method_get_nextSibling(CallContext *ctx) +void NodePrototype::method_get_nextSibling(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); if (!r->d()->d->parent) - return Encode::null(); + RETURN_RESULT(Encode::null()); for (int ii = 0; ii < r->d()->d->parent->children.count(); ++ii) { if (r->d()->d->parent->children.at(ii) == r->d()->d) { if ((ii + 1) == r->d()->d->parent->children.count()) - return Encode::null(); + scope.result = Encode::null(); else - return Node::create(scope.engine, r->d()->d->parent->children.at(ii + 1)); + scope.result = Node::create(scope.engine, r->d()->d->parent->children.at(ii + 1)); + return; } } - return Encode::null(); + scope.result = Encode::null(); } -ReturnedValue NodePrototype::method_get_attributes(CallContext *ctx) +void NodePrototype::method_get_attributes(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); if (r->d()->d->type != NodeImpl::Element) - return Encode::null(); + scope.result = Encode::null(); else - return NamedNodeMap::create(scope.engine, r->d()->d, r->d()->d->attributes); + scope.result = NamedNodeMap::create(scope.engine, r->d()->d, r->d()->d->attributes); } ReturnedValue NodePrototype::getProto(ExecutionEngine *v4) @@ -666,44 +659,40 @@ ReturnedValue Attr::prototype(ExecutionEngine *engine) return d->attrPrototype.value(); } -ReturnedValue Attr::method_name(CallContext *ctx) +void Attr::method_name(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return Encode::undefined(); + RETURN_UNDEFINED(); - return QV4::Encode(scope.engine->newString(r->d()->d->name)); + scope.result = scope.engine->newString(r->d()->d->name); } -ReturnedValue Attr::method_value(CallContext *ctx) +void Attr::method_value(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return Encode::undefined(); + RETURN_UNDEFINED(); - return QV4::Encode(scope.engine->newString(r->d()->d->data)); + scope.result = scope.engine->newString(r->d()->d->data); } -ReturnedValue Attr::method_ownerElement(CallContext *ctx) +void Attr::method_ownerElement(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return Encode::undefined(); + RETURN_UNDEFINED(); - return Node::create(scope.engine, r->d()->d->parent); + scope.result = Node::create(scope.engine, r->d()->d->parent); } -ReturnedValue CharacterData::method_length(CallContext *ctx) +void CharacterData::method_length(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return Encode::undefined(); + RETURN_UNDEFINED(); - return Encode(r->d()->d->data.length()); + scope.result = Encode(r->d()->d->data.length()); } ReturnedValue CharacterData::prototype(ExecutionEngine *v4) @@ -722,23 +711,22 @@ ReturnedValue CharacterData::prototype(ExecutionEngine *v4) return d->characterDataPrototype.value(); } -ReturnedValue Text::method_isElementContentWhitespace(CallContext *ctx) +void Text::method_isElementContentWhitespace(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); - if (!r) return Encode::undefined(); + Scoped r(scope, callData->thisObject.as()); + if (!r) + RETURN_UNDEFINED(); - return Encode(QStringRef(&r->d()->d->data).trimmed().isEmpty()); + scope.result = Encode(QStringRef(&r->d()->d->data).trimmed().isEmpty()); } -ReturnedValue Text::method_wholeText(CallContext *ctx) +void Text::method_wholeText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r) - return Encode::undefined(); + RETURN_UNDEFINED(); - return QV4::Encode(scope.engine->newString(r->d()->d->data)); + scope.result = scope.engine->newString(r->d()->d->data); } ReturnedValue Text::prototype(ExecutionEngine *v4) @@ -964,44 +952,40 @@ ReturnedValue NodeList::create(ExecutionEngine *v4, NodeImpl *data) return (v4->memoryManager->allocObject(data))->asReturnedValue(); } -ReturnedValue Document::method_documentElement(CallContext *ctx) +void Document::method_documentElement(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r || r->d()->d->type != NodeImpl::Document) - return Encode::undefined(); + RETURN_UNDEFINED(); - return Node::create(scope.engine, static_cast(r->d()->d)->root); + scope.result = Node::create(scope.engine, static_cast(r->d()->d)->root); } -ReturnedValue Document::method_xmlStandalone(CallContext *ctx) +void Document::method_xmlStandalone(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r || r->d()->d->type != NodeImpl::Document) - return Encode::undefined(); + RETURN_UNDEFINED(); - return Encode(static_cast(r->d()->d)->isStandalone); + scope.result = Encode(static_cast(r->d()->d)->isStandalone); } -ReturnedValue Document::method_xmlVersion(CallContext *ctx) +void Document::method_xmlVersion(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r || r->d()->d->type != NodeImpl::Document) - return Encode::undefined(); + RETURN_UNDEFINED(); - return QV4::Encode(scope.engine->newString(static_cast(r->d()->d)->version)); + scope.result = scope.engine->newString(static_cast(r->d()->d)->version); } -ReturnedValue Document::method_xmlEncoding(CallContext *ctx) +void Document::method_xmlEncoding(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped r(scope, ctx->thisObject().as()); + Scoped r(scope, callData->thisObject.as()); if (!r || r->d()->d->type != NodeImpl::Document) - return Encode::undefined(); + RETURN_UNDEFINED(); - return QV4::Encode(scope.engine->newString(static_cast(r->d()->d)->encoding)); + scope.result = scope.engine->newString(static_cast(r->d()->d)->encoding); } class QQmlXMLHttpRequest : public QObject @@ -1657,21 +1641,21 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject void setupProto(); - static ReturnedValue method_open(CallContext *ctx); - static ReturnedValue method_setRequestHeader(CallContext *ctx); - static ReturnedValue method_send(CallContext *ctx); - static ReturnedValue method_abort(CallContext *ctx); - static ReturnedValue method_getResponseHeader(CallContext *ctx); - static ReturnedValue method_getAllResponseHeaders(CallContext *ctx); - - static ReturnedValue method_get_readyState(CallContext *ctx); - static ReturnedValue method_get_status(CallContext *ctx); - static ReturnedValue method_get_statusText(CallContext *ctx); - static ReturnedValue method_get_responseText(CallContext *ctx); - static ReturnedValue method_get_responseXML(CallContext *ctx); - static ReturnedValue method_get_response(CallContext *ctx); - static ReturnedValue method_get_responseType(CallContext *ctx); - static ReturnedValue method_set_responseType(CallContext *ctx); + static void method_open(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_setRequestHeader(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_send(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_abort(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_getResponseHeader(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_getAllResponseHeaders(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + + static void method_get_readyState(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_status(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_statusText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_responseText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_responseXML(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_response(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_responseType(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_responseType(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); }; } @@ -1733,19 +1717,18 @@ void QQmlXMLHttpRequestCtor::setupProto() // XMLHttpRequest methods -ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx) +void QQmlXMLHttpRequestCtor::method_open(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped w(scope, ctx->thisObject().as()); + Scoped w(scope, callData->thisObject.as()); if (!w) V4THROW_REFERENCE("Not an XMLHttpRequest object"); QQmlXMLHttpRequest *r = w->d()->request; - if (ctx->argc() < 2 || ctx->argc() > 5) - V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count"); + if (callData->argc < 2 || callData->argc > 5) + THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count"); // Argument 0 - Method - QString method = ctx->args()[0].toQStringNoThrow().toUpper(); + QString method = callData->args[0].toQStringNoThrow().toUpper(); if (method != QLatin1String("GET") && method != QLatin1String("PUT") && method != QLatin1String("HEAD") && @@ -1754,26 +1737,26 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx) method != QLatin1String("OPTIONS") && method != QLatin1String("PROPFIND") && method != QLatin1String("PATCH")) - V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Unsupported HTTP method type"); + THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Unsupported HTTP method type"); // Argument 1 - URL - QUrl url = QUrl(ctx->args()[1].toQStringNoThrow()); + QUrl url = QUrl(callData->args[1].toQStringNoThrow()); if (url.isRelative()) url = scope.engine->callingQmlContext()->resolvedUrl(url); bool async = true; // Argument 2 - async (optional) - if (ctx->argc() > 2) { - async = ctx->args()[2].booleanValue(); + if (callData->argc > 2) { + async = callData->args[2].booleanValue(); } // Argument 3/4 - user/pass (optional) QString username, password; - if (ctx->argc() > 3) - username = ctx->args()[3].toQStringNoThrow(); - if (ctx->argc() > 4) - password = ctx->args()[4].toQStringNoThrow(); + if (callData->argc > 3) + username = callData->args[3].toQStringNoThrow(); + if (callData->argc > 4) + password = callData->args[4].toQStringNoThrow(); // Clear the fragment (if any) url.setFragment(QString()); @@ -1782,25 +1765,24 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx) if (!username.isNull()) url.setUserName(username); if (!password.isNull()) url.setPassword(password); - return r->open(w, scope.engine->callingQmlContext(), method, url, async ? QQmlXMLHttpRequest::AsynchronousLoad : QQmlXMLHttpRequest::SynchronousLoad); + scope.result = r->open(w, scope.engine->callingQmlContext(), method, url, async ? QQmlXMLHttpRequest::AsynchronousLoad : QQmlXMLHttpRequest::SynchronousLoad); } -ReturnedValue QQmlXMLHttpRequestCtor::method_setRequestHeader(CallContext *ctx) +void QQmlXMLHttpRequestCtor::method_setRequestHeader(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped w(scope, ctx->thisObject().as()); + Scoped w(scope, callData->thisObject.as()); if (!w) V4THROW_REFERENCE("Not an XMLHttpRequest object"); QQmlXMLHttpRequest *r = w->d()->request; - if (ctx->argc() != 2) - V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count"); + if (callData->argc != 2) + THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count"); if (r->readyState() != QQmlXMLHttpRequest::Opened || r->sendFlag()) - V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state"); + THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state"); - QString name = ctx->args()[0].toQStringNoThrow(); - QString value = ctx->args()[1].toQStringNoThrow(); + QString name = callData->args[0].toQStringNoThrow(); + QString value = callData->args[1].toQStringNoThrow(); // ### Check that name and value are well formed @@ -1825,148 +1807,139 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_setRequestHeader(CallContext *ctx) nameUpper == QLatin1String("VIA") || nameUpper.startsWith(QLatin1String("PROXY-")) || nameUpper.startsWith(QLatin1String("SEC-"))) - return Encode::undefined(); + RETURN_UNDEFINED(); r->addHeader(name, value); - return Encode::undefined(); + RETURN_UNDEFINED(); } -ReturnedValue QQmlXMLHttpRequestCtor::method_send(CallContext *ctx) +void QQmlXMLHttpRequestCtor::method_send(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped w(scope, ctx->thisObject().as()); + Scoped w(scope, callData->thisObject.as()); if (!w) V4THROW_REFERENCE("Not an XMLHttpRequest object"); QQmlXMLHttpRequest *r = w->d()->request; if (r->readyState() != QQmlXMLHttpRequest::Opened || r->sendFlag()) - V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state"); + THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state"); QByteArray data; - if (ctx->argc() > 0) - data = ctx->args()[0].toQStringNoThrow().toUtf8(); + if (callData->argc > 0) + data = callData->args[0].toQStringNoThrow().toUtf8(); - return r->send(w, scope.engine->callingQmlContext(), data); + scope.result = r->send(w, scope.engine->callingQmlContext(), data); } -ReturnedValue QQmlXMLHttpRequestCtor::method_abort(CallContext *ctx) +void QQmlXMLHttpRequestCtor::method_abort(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped w(scope, ctx->thisObject().as()); + Scoped w(scope, callData->thisObject.as()); if (!w) V4THROW_REFERENCE("Not an XMLHttpRequest object"); QQmlXMLHttpRequest *r = w->d()->request; - return r->abort(w, scope.engine->callingQmlContext()); + scope.result = r->abort(w, scope.engine->callingQmlContext()); } -ReturnedValue QQmlXMLHttpRequestCtor::method_getResponseHeader(CallContext *ctx) +void QQmlXMLHttpRequestCtor::method_getResponseHeader(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped w(scope, ctx->thisObject().as()); + Scoped w(scope, callData->thisObject.as()); if (!w) V4THROW_REFERENCE("Not an XMLHttpRequest object"); QQmlXMLHttpRequest *r = w->d()->request; - if (ctx->argc() != 1) - V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count"); + if (callData->argc != 1) + THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count"); if (r->readyState() != QQmlXMLHttpRequest::Loading && r->readyState() != QQmlXMLHttpRequest::Done && r->readyState() != QQmlXMLHttpRequest::HeadersReceived) - V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state"); + THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state"); - return QV4::Encode(scope.engine->newString(r->header(ctx->args()[0].toQStringNoThrow()))); + scope.result = scope.engine->newString(r->header(callData->args[0].toQStringNoThrow())); } -ReturnedValue QQmlXMLHttpRequestCtor::method_getAllResponseHeaders(CallContext *ctx) +void QQmlXMLHttpRequestCtor::method_getAllResponseHeaders(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped w(scope, ctx->thisObject().as()); + Scoped w(scope, callData->thisObject.as()); if (!w) V4THROW_REFERENCE("Not an XMLHttpRequest object"); QQmlXMLHttpRequest *r = w->d()->request; - if (ctx->argc() != 0) - V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count"); + if (callData->argc != 0) + THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count"); if (r->readyState() != QQmlXMLHttpRequest::Loading && r->readyState() != QQmlXMLHttpRequest::Done && r->readyState() != QQmlXMLHttpRequest::HeadersReceived) - V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state"); + THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state"); - return QV4::Encode(scope.engine->newString(r->headers())); + scope.result = scope.engine->newString(r->headers()); } // XMLHttpRequest properties -ReturnedValue QQmlXMLHttpRequestCtor::method_get_readyState(CallContext *ctx) +void QQmlXMLHttpRequestCtor::method_get_readyState(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped w(scope, ctx->thisObject().as()); + Scoped w(scope, callData->thisObject.as()); if (!w) V4THROW_REFERENCE("Not an XMLHttpRequest object"); QQmlXMLHttpRequest *r = w->d()->request; - return Encode(r->readyState()); + scope.result = Encode(r->readyState()); } -ReturnedValue QQmlXMLHttpRequestCtor::method_get_status(CallContext *ctx) +void QQmlXMLHttpRequestCtor::method_get_status(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped w(scope, ctx->thisObject().as()); + Scoped w(scope, callData->thisObject.as()); if (!w) V4THROW_REFERENCE("Not an XMLHttpRequest object"); QQmlXMLHttpRequest *r = w->d()->request; if (r->readyState() == QQmlXMLHttpRequest::Unsent || r->readyState() == QQmlXMLHttpRequest::Opened) - V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state"); + THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state"); if (r->errorFlag()) - return Encode(0); + scope.result = Encode(0); else - return Encode(r->replyStatus()); + scope.result = Encode(r->replyStatus()); } -ReturnedValue QQmlXMLHttpRequestCtor::method_get_statusText(CallContext *ctx) +void QQmlXMLHttpRequestCtor::method_get_statusText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped w(scope, ctx->thisObject().as()); + Scoped w(scope, callData->thisObject.as()); if (!w) V4THROW_REFERENCE("Not an XMLHttpRequest object"); QQmlXMLHttpRequest *r = w->d()->request; if (r->readyState() == QQmlXMLHttpRequest::Unsent || r->readyState() == QQmlXMLHttpRequest::Opened) - V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state"); + THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state"); if (r->errorFlag()) - return QV4::Encode(scope.engine->newString(QString())); + scope.result = scope.engine->newString(QString()); else - return QV4::Encode(scope.engine->newString(r->replyStatusText())); + scope.result = scope.engine->newString(r->replyStatusText()); } -ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseText(CallContext *ctx) +void QQmlXMLHttpRequestCtor::method_get_responseText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped w(scope, ctx->thisObject().as()); + Scoped w(scope, callData->thisObject.as()); if (!w) V4THROW_REFERENCE("Not an XMLHttpRequest object"); QQmlXMLHttpRequest *r = w->d()->request; if (r->readyState() != QQmlXMLHttpRequest::Loading && r->readyState() != QQmlXMLHttpRequest::Done) - return QV4::Encode(scope.engine->newString(QString())); + scope.result = scope.engine->newString(QString()); else - return QV4::Encode(scope.engine->newString(r->responseBody())); + scope.result = scope.engine->newString(r->responseBody()); } -ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseXML(CallContext *ctx) +void QQmlXMLHttpRequestCtor::method_get_responseXML(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped w(scope, ctx->thisObject().as()); + Scoped w(scope, callData->thisObject.as()); if (!w) V4THROW_REFERENCE("Not an XMLHttpRequest object"); QQmlXMLHttpRequest *r = w->d()->request; @@ -1974,66 +1947,63 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseXML(CallContext *ctx) if (!r->receivedXml() || (r->readyState() != QQmlXMLHttpRequest::Loading && r->readyState() != QQmlXMLHttpRequest::Done)) { - return Encode::null(); + scope.result = Encode::null(); } else { if (r->responseType().isEmpty()) r->setResponseType(QLatin1String("document")); - return r->xmlResponseBody(scope.engine); + scope.result = r->xmlResponseBody(scope.engine); } } -ReturnedValue QQmlXMLHttpRequestCtor::method_get_response(CallContext *ctx) +void QQmlXMLHttpRequestCtor::method_get_response(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped w(scope, ctx->thisObject().as()); + Scoped w(scope, callData->thisObject.as()); if (!w) V4THROW_REFERENCE("Not an XMLHttpRequest object"); QQmlXMLHttpRequest *r = w->d()->request; if (r->readyState() != QQmlXMLHttpRequest::Loading && r->readyState() != QQmlXMLHttpRequest::Done) - return QV4::Encode(scope.engine->newString(QString())); + RETURN_RESULT(scope.engine->newString(QString())); const QString& responseType = r->responseType(); if (responseType.compare(QLatin1String("text"), Qt::CaseInsensitive) == 0 || responseType.isEmpty()) { - return QV4::Encode(scope.engine->newString(r->responseBody())); + RETURN_RESULT(scope.engine->newString(r->responseBody())); } else if (responseType.compare(QLatin1String("arraybuffer"), Qt::CaseInsensitive) == 0) { - return QV4::Encode(scope.engine->newArrayBuffer(r->rawResponseBody())); + RETURN_RESULT(scope.engine->newArrayBuffer(r->rawResponseBody())); } else if (responseType.compare(QLatin1String("json"), Qt::CaseInsensitive) == 0) { - return r->jsonResponseBody(scope.engine); + RETURN_RESULT(r->jsonResponseBody(scope.engine)); } else if (responseType.compare(QLatin1String("document"), Qt::CaseInsensitive) == 0) { - return r->xmlResponseBody(scope.engine); + RETURN_RESULT(r->xmlResponseBody(scope.engine)); } else { - return QV4::Encode(scope.engine->newString(QString())); + RETURN_RESULT(scope.engine->newString(QString())); } } -ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseType(CallContext *ctx) +void QQmlXMLHttpRequestCtor::method_get_responseType(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped w(scope, ctx->thisObject().as()); + Scoped w(scope, callData->thisObject.as()); if (!w) V4THROW_REFERENCE("Not an XMLHttpRequest object"); QQmlXMLHttpRequest *r = w->d()->request; - return QV4::Encode(scope.engine->newString(r->responseType())); + scope.result = scope.engine->newString(r->responseType()); } -ReturnedValue QQmlXMLHttpRequestCtor::method_set_responseType(CallContext *ctx) +void QQmlXMLHttpRequestCtor::method_set_responseType(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - Scope scope(ctx); - Scoped w(scope, ctx->thisObject().as()); + Scoped w(scope, callData->thisObject.as()); if (!w) V4THROW_REFERENCE("Not an XMLHttpRequest object"); QQmlXMLHttpRequest *r = w->d()->request; - if (ctx->argc() < 1) - V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count"); + if (callData->argc < 1) + THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count"); // Argument 0 - response type - r->setResponseType(ctx->args()[0].toQStringNoThrow()); + r->setResponseType(callData->args[0].toQStringNoThrow()); - return Encode::undefined(); + scope.result = Encode::undefined(); } void qt_rem_qmlxmlhttprequest(ExecutionEngine * /* engine */, void *d) diff --git a/src/qml/qml/v8/qv4domerrors_p.h b/src/qml/qml/v8/qv4domerrors_p.h index faa9dd8bc7..d2225ec591 100644 --- a/src/qml/qml/v8/qv4domerrors_p.h +++ b/src/qml/qml/v8/qv4domerrors_p.h @@ -81,6 +81,14 @@ QT_BEGIN_NAMESPACE return ctx->engine()->throwError(ex); \ } +#define THROW_DOM(error, string) { \ + QV4::ScopedValue v(scope, scope.engine->newString(QStringLiteral(string))); \ + QV4::ScopedObject ex(scope, scope.engine->newErrorObject(v)); \ + ex->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("code"))), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(error))); \ + scope.result = scope.engine->throwError(ex); \ + return; \ +} + namespace QV4 { struct ExecutionEngine; } diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index c0d75cae33..a5878dcffd 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -1795,24 +1795,26 @@ int QQmlDelegateModelItemMetaType::parseGroups(const QV4::Value &groups) const return groupFlags; } -QV4::ReturnedValue QQmlDelegateModelItem::get_model(QV4::CallContext *ctx) +void QQmlDelegateModelItem::get_model(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped o(scope, ctx->thisObject().as()); - if (!o) - return ctx->engine()->throwTypeError(QStringLiteral("Not a valid VisualData object")); + QV4::Scoped o(scope, callData->thisObject.as()); + if (!o) { + scope.result = scope.engine->throwTypeError(QStringLiteral("Not a valid VisualData object")); + return; + } if (!o->d()->item->metaType->model) - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); - return o->d()->item->get(); + scope.result = o->d()->item->get(); } -QV4::ReturnedValue QQmlDelegateModelItem::get_groups(QV4::CallContext *ctx) +void QQmlDelegateModelItem::get_groups(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped o(scope, ctx->thisObject().as()); - if (!o) - return ctx->engine()->throwTypeError(QStringLiteral("Not a valid VisualData object")); + QV4::Scoped o(scope, callData->thisObject.as()); + if (!o) { + scope.result = scope.engine->throwTypeError(QStringLiteral("Not a valid VisualData object")); + return; + } QStringList groups; for (int i = 1; i < o->d()->item->metaType->groupCount; ++i) { @@ -1820,27 +1822,29 @@ QV4::ReturnedValue QQmlDelegateModelItem::get_groups(QV4::CallContext *ctx) groups.append(o->d()->item->metaType->groupNames.at(i - 1)); } - return scope.engine->fromVariant(groups); + scope.result = scope.engine->fromVariant(groups); } -QV4::ReturnedValue QQmlDelegateModelItem::set_groups(QV4::CallContext *ctx) +void QQmlDelegateModelItem::set_groups(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped o(scope, ctx->thisObject().as()); - if (!o) - return ctx->engine()->throwTypeError(QStringLiteral("Not a valid VisualData object")); - if (!ctx->argc()) - return ctx->engine()->throwTypeError(); + QV4::Scoped o(scope, callData->thisObject.as()); + if (!o) { + scope.result = scope.engine->throwTypeError(QStringLiteral("Not a valid VisualData object")); + return; + } + + if (!callData->argc) + THROW_TYPE_ERROR(); if (!o->d()->item->metaType->model) - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(o->d()->item->metaType->model); - const int groupFlags = model->m_cacheMetaType->parseGroups(ctx->args()[0]); + const int groupFlags = model->m_cacheMetaType->parseGroups(callData->args[0]); const int cacheIndex = model->m_cache.indexOf(o->d()->item); Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex); model->setGroups(it, 1, Compositor::Cache, groupFlags); - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } QV4::ReturnedValue QQmlDelegateModelItem::get_member(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &) @@ -3234,28 +3238,25 @@ struct QQmlDelegateModelGroupChange : QV4::Object return e->memoryManager->allocObject(); } - static QV4::ReturnedValue method_get_index(QV4::CallContext *ctx) { - QV4::Scope scope(ctx); - QV4::Scoped that(scope, ctx->thisObject().as()); + static void method_get_index(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { + QV4::Scoped that(scope, callData->thisObject.as()); if (!that) - return ctx->engine()->throwTypeError(); - return QV4::Encode(that->d()->change.index); + THROW_TYPE_ERROR(); + scope.result = QV4::Encode(that->d()->change.index); } - static QV4::ReturnedValue method_get_count(QV4::CallContext *ctx) { - QV4::Scope scope(ctx); - QV4::Scoped that(scope, ctx->thisObject().as()); + static void method_get_count(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { + QV4::Scoped that(scope, callData->thisObject.as()); if (!that) - return ctx->engine()->throwTypeError(); - return QV4::Encode(that->d()->change.count); + THROW_TYPE_ERROR(); + scope.result = QV4::Encode(that->d()->change.count); } - static QV4::ReturnedValue method_get_moveId(QV4::CallContext *ctx) { - QV4::Scope scope(ctx); - QV4::Scoped that(scope, ctx->thisObject().as()); + static void method_get_moveId(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { + QV4::Scoped that(scope, callData->thisObject.as()); if (!that) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); if (that->d()->change.moveId < 0) - return QV4::Encode::undefined(); - return QV4::Encode(that->d()->change.moveId); + RETURN_UNDEFINED(); + scope.result = QV4::Encode(that->d()->change.moveId); } }; diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h index 4c2841b8ba..cb4a1f79ba 100644 --- a/src/qml/types/qqmldelegatemodel_p_p.h +++ b/src/qml/types/qqmldelegatemodel_p_p.h @@ -131,9 +131,9 @@ public: virtual void setValue(const QString &role, const QVariant &value) { Q_UNUSED(role); Q_UNUSED(value); } virtual bool resolveIndex(const QQmlAdaptorModel &, int) { return false; } - static QV4::ReturnedValue get_model(QV4::CallContext *ctx); - static QV4::ReturnedValue get_groups(QV4::CallContext *ctx); - static QV4::ReturnedValue set_groups(QV4::CallContext *ctx); + static void get_model(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void get_groups(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void set_groups(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); static QV4::ReturnedValue get_member(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &); static QV4::ReturnedValue set_member(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &arg); static QV4::ReturnedValue get_index(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &arg); diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp index 5f716da17a..f35e17c34d 100644 --- a/src/qml/types/qquickworkerscript.cpp +++ b/src/qml/types/qquickworkerscript.cpp @@ -185,7 +185,7 @@ public: int m_nextId; - static QV4::ReturnedValue method_sendMessage(QV4::CallContext *ctx); + static void method_sendMessage(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); signals: void stopThread(); @@ -292,14 +292,13 @@ QQuickWorkerScriptEnginePrivate::QQuickWorkerScriptEnginePrivate(QQmlEngine *eng { } -QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::method_sendMessage(QV4::CallContext *ctx) +void QQuickWorkerScriptEnginePrivate::method_sendMessage(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - WorkerEngine *engine = (WorkerEngine*)ctx->engine()->v8Engine; + WorkerEngine *engine = (WorkerEngine*)scope.engine->v8Engine; - int id = ctx->argc() > 1 ? ctx->args()[1].toInt32() : 0; + int id = callData->argc > 1 ? callData->args[1].toInt32() : 0; - QV4::Scope scope(ctx); - QV4::ScopedValue v(scope, ctx->argument(2)); + QV4::ScopedValue v(scope, callData->argument(2)); QByteArray data = QV4::Serialize::serialize(v, scope.engine); QMutexLocker locker(&engine->p->m_lock); @@ -307,7 +306,7 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::method_sendMessage(QV4::Call if (script && script->owner) QCoreApplication::postEvent(script->owner, new WorkerDataEvent(0, data)); - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *script) -- cgit v1.2.3 From 064ca8fc81b9db621fbbda89e10456c27db0c0d1 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 5 Jan 2017 23:00:25 +0100 Subject: Convert the last remaining builtin function to the new calling convention Change-Id: Iee18ce53111dcd080780e8125d9c65c960c9e604 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmldelayedcallqueue.cpp | 10 +- src/qml/qml/qqmldelayedcallqueue_p.h | 2 +- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 865 ++++++++++++++++---------------- src/qml/qml/v8/qqmlbuiltinfunctions_p.h | 118 ++--- 4 files changed, 505 insertions(+), 490 deletions(-) diff --git a/src/qml/qml/qqmldelayedcallqueue.cpp b/src/qml/qml/qqmldelayedcallqueue.cpp index 7552e1e82b..d5d2c9a28d 100644 --- a/src/qml/qml/qqmldelayedcallqueue.cpp +++ b/src/qml/qml/qqmldelayedcallqueue.cpp @@ -105,17 +105,15 @@ void QQmlDelayedCallQueue::init(QV4::ExecutionEngine* engine) m_tickedMethod = metaObject.method(methodIndex); } -QV4::ReturnedValue QQmlDelayedCallQueue::addUniquelyAndExecuteLater(QV4::CallContext *ctx) +void QQmlDelayedCallQueue::addUniquelyAndExecuteLater(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - const QV4::CallData *callData = ctx->d()->callData; - if (callData->argc == 0) - V4THROW_ERROR("Qt.callLater: no arguments given"); + THROW_GENERIC_ERROR("Qt.callLater: no arguments given"); const QV4::FunctionObject *func = callData->args[0].as(); if (!func) - V4THROW_ERROR("Qt.callLater: first argument not a function or signal"); + THROW_GENERIC_ERROR("Qt.callLater: first argument not a function or signal"); QPair functionData = QV4::QObjectMethod::extractQtMethod(func); @@ -171,7 +169,7 @@ QV4::ReturnedValue QQmlDelayedCallQueue::addUniquelyAndExecuteLater(QV4::CallCon m_tickedMethod.invoke(this, Qt::QueuedConnection); m_callbackOutstanding = true; } - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } void QQmlDelayedCallQueue::storeAnyArguments(DelayedFunctionCall &dfc, const QV4::CallData *callData, int offset, QV4::ExecutionEngine *engine) diff --git a/src/qml/qml/qqmldelayedcallqueue_p.h b/src/qml/qml/qqmldelayedcallqueue_p.h index ef899170a2..cffde4f0c0 100644 --- a/src/qml/qml/qqmldelayedcallqueue_p.h +++ b/src/qml/qml/qqmldelayedcallqueue_p.h @@ -70,7 +70,7 @@ public: void init(QV4::ExecutionEngine *); - QV4::ReturnedValue addUniquelyAndExecuteLater(QV4::CallContext *ctx); + void addUniquelyAndExecuteLater(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); public Q_SLOTS: void ticked(); diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 19dc100f40..d359a0f62f 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -85,6 +85,12 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(QtObject); +#define THROW_TYPE_ERROR_WITH_MESSAGE(msg) \ + do { \ + scope.result = scope.engine->throwTypeError(QString::fromUtf8(msg)); \ + return; \ + } while (false) + struct StaticQtMetaObject : public QObject { static const QMetaObject *get() @@ -223,12 +229,12 @@ void QtObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint \qmlmethod bool Qt::isQtObject(object) Returns true if \c object is a valid reference to a Qt or QML object, otherwise false. */ -ReturnedValue QtObject::method_isQtObject(QV4::CallContext *ctx) +void QtObject::method_isQtObject(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() == 0) - return QV4::Encode(false); + if (callData->argc == 0) + RETURN_RESULT(QV4::Encode(false)); - return QV4::Encode(ctx->args()[0].as() != 0); + scope.result = QV4::Encode(callData->args[0].as() != 0); } /*! @@ -237,16 +243,16 @@ ReturnedValue QtObject::method_isQtObject(QV4::CallContext *ctx) Returns a color with the specified \c red, \c green, \c blue and \c alpha components. All components should be in the range 0-1 inclusive. */ -ReturnedValue QtObject::method_rgba(QV4::CallContext *ctx) +void QtObject::method_rgba(const BuiltinFunction *, Scope &scope, CallData *callData) { - int argCount = ctx->argc(); + int argCount = callData->argc; if (argCount < 3 || argCount > 4) - V4THROW_ERROR("Qt.rgba(): Invalid arguments"); + THROW_GENERIC_ERROR("Qt.rgba(): Invalid arguments"); - double r = ctx->args()[0].toNumber(); - double g = ctx->args()[1].toNumber(); - double b = ctx->args()[2].toNumber(); - double a = (argCount == 4) ? ctx->args()[3].toNumber() : 1; + double r = callData->args[0].toNumber(); + double g = callData->args[1].toNumber(); + double b = callData->args[2].toNumber(); + double a = (argCount == 4) ? callData->args[3].toNumber() : 1; if (r < 0.0) r=0.0; if (r > 1.0) r=1.0; @@ -257,7 +263,7 @@ ReturnedValue QtObject::method_rgba(QV4::CallContext *ctx) if (a < 0.0) a=0.0; if (a > 1.0) a=1.0; - return ctx->engine()->fromVariant(QQml_colorProvider()->fromRgbF(r, g, b, a)); + scope.result = scope.engine->fromVariant(QQml_colorProvider()->fromRgbF(r, g, b, a)); } /*! @@ -266,16 +272,16 @@ ReturnedValue QtObject::method_rgba(QV4::CallContext *ctx) Returns a color with the specified \c hue, \c saturation, \c lightness and \c alpha components. All components should be in the range 0-1 inclusive. */ -ReturnedValue QtObject::method_hsla(QV4::CallContext *ctx) +void QtObject::method_hsla(const BuiltinFunction *, Scope &scope, CallData *callData) { - int argCount = ctx->argc(); + int argCount = callData->argc; if (argCount < 3 || argCount > 4) - V4THROW_ERROR("Qt.hsla(): Invalid arguments"); + THROW_GENERIC_ERROR("Qt.hsla(): Invalid arguments"); - double h = ctx->args()[0].toNumber(); - double s = ctx->args()[1].toNumber(); - double l = ctx->args()[2].toNumber(); - double a = (argCount == 4) ? ctx->args()[3].toNumber() : 1; + double h = callData->args[0].toNumber(); + double s = callData->args[1].toNumber(); + double l = callData->args[2].toNumber(); + double a = (argCount == 4) ? callData->args[3].toNumber() : 1; if (h < 0.0) h=0.0; if (h > 1.0) h=1.0; @@ -286,7 +292,7 @@ ReturnedValue QtObject::method_hsla(QV4::CallContext *ctx) if (a < 0.0) a=0.0; if (a > 1.0) a=1.0; - return ctx->engine()->fromVariant(QQml_colorProvider()->fromHslF(h, s, l, a)); + scope.result = scope.engine->fromVariant(QQml_colorProvider()->fromHslF(h, s, l, a)); } /*! @@ -297,23 +303,23 @@ All components should be in the range 0-1 inclusive. \since 5.5 */ -ReturnedValue QtObject::method_hsva(QV4::CallContext *ctx) +void QtObject::method_hsva(const BuiltinFunction *, Scope &scope, CallData *callData) { - int argCount = ctx->argc(); + int argCount = callData->argc; if (argCount < 3 || argCount > 4) - V4THROW_ERROR("Qt.hsva(): Invalid arguments"); + THROW_GENERIC_ERROR("Qt.hsva(): Invalid arguments"); - double h = ctx->args()[0].toNumber(); - double s = ctx->args()[1].toNumber(); - double v = ctx->args()[2].toNumber(); - double a = (argCount == 4) ? ctx->args()[3].toNumber() : 1; + double h = callData->args[0].toNumber(); + double s = callData->args[1].toNumber(); + double v = callData->args[2].toNumber(); + double a = (argCount == 4) ? callData->args[3].toNumber() : 1; h = qBound(0.0, h, 1.0); s = qBound(0.0, s, 1.0); v = qBound(0.0, v, 1.0); a = qBound(0.0, a, 1.0); - return ctx->engine()->fromVariant(QQml_colorProvider()->fromHsvF(h, s, v, a)); + scope.result = scope.engine->fromVariant(QQml_colorProvider()->fromHsvF(h, s, v, a)); } /*! @@ -324,35 +330,35 @@ may be either color values or string values. If a string value is supplied it must be convertible to a color, as described for the \l{colorbasictypedocs}{color} basic type. */ -ReturnedValue QtObject::method_colorEqual(QV4::CallContext *ctx) +void QtObject::method_colorEqual(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 2) - V4THROW_ERROR("Qt.colorEqual(): Invalid arguments"); + if (callData->argc != 2) + THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid arguments"); bool ok = false; - QVariant lhs = ctx->d()->engine->toVariant(ctx->args()[0], -1); + QVariant lhs = scope.engine->toVariant(callData->args[0], -1); if (lhs.userType() == QVariant::String) { lhs = QQmlStringConverters::colorFromString(lhs.toString(), &ok); if (!ok) { - V4THROW_ERROR("Qt.colorEqual(): Invalid color name"); + THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid color name"); } } else if (lhs.userType() != QVariant::Color) { - V4THROW_ERROR("Qt.colorEqual(): Invalid arguments"); + THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid arguments"); } - QVariant rhs = ctx->engine()->toVariant(ctx->args()[1], -1); + QVariant rhs = scope.engine->toVariant(callData->args[1], -1); if (rhs.userType() == QVariant::String) { rhs = QQmlStringConverters::colorFromString(rhs.toString(), &ok); if (!ok) { - V4THROW_ERROR("Qt.colorEqual(): Invalid color name"); + THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid color name"); } } else if (rhs.userType() != QVariant::Color) { - V4THROW_ERROR("Qt.colorEqual(): Invalid arguments"); + THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid arguments"); } bool equal = (lhs == rhs); - return QV4::Encode(equal); + scope.result = QV4::Encode(equal); } /*! @@ -362,47 +368,47 @@ Returns a \c rect with the top-left corner at \c x, \c y and the specified \c wi The returned object has \c x, \c y, \c width and \c height attributes with the given values. */ -ReturnedValue QtObject::method_rect(QV4::CallContext *ctx) +void QtObject::method_rect(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 4) - V4THROW_ERROR("Qt.rect(): Invalid arguments"); + if (callData->argc != 4) + THROW_GENERIC_ERROR("Qt.rect(): Invalid arguments"); - double x = ctx->args()[0].toNumber(); - double y = ctx->args()[1].toNumber(); - double w = ctx->args()[2].toNumber(); - double h = ctx->args()[3].toNumber(); + double x = callData->args[0].toNumber(); + double y = callData->args[1].toNumber(); + double w = callData->args[2].toNumber(); + double h = callData->args[3].toNumber(); - return ctx->engine()->fromVariant(QVariant::fromValue(QRectF(x, y, w, h))); + scope.result = scope.engine->fromVariant(QVariant::fromValue(QRectF(x, y, w, h))); } /*! \qmlmethod point Qt::point(int x, int y) Returns a Point with the specified \c x and \c y coordinates. */ -ReturnedValue QtObject::method_point(QV4::CallContext *ctx) +void QtObject::method_point(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 2) - V4THROW_ERROR("Qt.point(): Invalid arguments"); + if (callData->argc != 2) + THROW_GENERIC_ERROR("Qt.point(): Invalid arguments"); - double x = ctx->args()[0].toNumber(); - double y = ctx->args()[1].toNumber(); + double x = callData->args[0].toNumber(); + double y = callData->args[1].toNumber(); - return ctx->engine()->fromVariant(QVariant::fromValue(QPointF(x, y))); + scope.result = scope.engine->fromVariant(QVariant::fromValue(QPointF(x, y))); } /*! \qmlmethod Qt::size(int width, int height) Returns a Size with the specified \c width and \c height. */ -ReturnedValue QtObject::method_size(QV4::CallContext *ctx) +void QtObject::method_size(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 2) - V4THROW_ERROR("Qt.size(): Invalid arguments"); + if (callData->argc != 2) + THROW_GENERIC_ERROR("Qt.size(): Invalid arguments"); - double w = ctx->args()[0].toNumber(); - double h = ctx->args()[1].toNumber(); + double w = callData->args[0].toNumber(); + double h = callData->args[1].toNumber(); - return ctx->engine()->fromVariant(QVariant::fromValue(QSizeF(w, h))); + scope.result = scope.engine->fromVariant(QVariant::fromValue(QSizeF(w, h))); } /*! @@ -413,17 +419,17 @@ key-value pairs where valid keys are the \l{fontbasictypedocs}{font} type's subproperty names, and the values are valid values for each subproperty. Invalid keys will be ignored. */ -ReturnedValue QtObject::method_font(QV4::CallContext *ctx) +void QtObject::method_font(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 1 || !ctx->args()[0].isObject()) - V4THROW_ERROR("Qt.font(): Invalid arguments"); + if (callData->argc != 1 || !callData->args[0].isObject()) + THROW_GENERIC_ERROR("Qt.font(): Invalid arguments"); - QV4::ExecutionEngine *v4 = ctx->d()->engine; + QV4::ExecutionEngine *v4 = scope.engine; bool ok = false; - QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QFont, QQmlV4Handle(ctx->args()[0]), v4, &ok); + QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QFont, QQmlV4Handle(callData->args[0]), v4, &ok); if (!ok) - V4THROW_ERROR("Qt.font(): Invalid argument: no valid font subproperties specified"); - return ctx->engine()->fromVariant(v); + THROW_GENERIC_ERROR("Qt.font(): Invalid argument: no valid font subproperties specified"); + scope.result = scope.engine->fromVariant(v); } @@ -432,73 +438,73 @@ ReturnedValue QtObject::method_font(QV4::CallContext *ctx) \qmlmethod Qt::vector2d(real x, real y) Returns a Vector2D with the specified \c x and \c y. */ -ReturnedValue QtObject::method_vector2d(QV4::CallContext *ctx) +void QtObject::method_vector2d(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 2) - V4THROW_ERROR("Qt.vector2d(): Invalid arguments"); + if (callData->argc != 2) + THROW_GENERIC_ERROR("Qt.vector2d(): Invalid arguments"); float xy[3]; // qvector2d uses float internally - xy[0] = ctx->args()[0].toNumber(); - xy[1] = ctx->args()[1].toNumber(); + xy[0] = callData->args[0].toNumber(); + xy[1] = callData->args[1].toNumber(); const void *params[] = { xy }; - return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector2D, 1, params)); + scope.result = scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector2D, 1, params)); } /*! \qmlmethod Qt::vector3d(real x, real y, real z) Returns a Vector3D with the specified \c x, \c y and \c z. */ -ReturnedValue QtObject::method_vector3d(QV4::CallContext *ctx) +void QtObject::method_vector3d(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 3) - V4THROW_ERROR("Qt.vector3d(): Invalid arguments"); + if (callData->argc != 3) + THROW_GENERIC_ERROR("Qt.vector3d(): Invalid arguments"); float xyz[3]; // qvector3d uses float internally - xyz[0] = ctx->args()[0].toNumber(); - xyz[1] = ctx->args()[1].toNumber(); - xyz[2] = ctx->args()[2].toNumber(); + xyz[0] = callData->args[0].toNumber(); + xyz[1] = callData->args[1].toNumber(); + xyz[2] = callData->args[2].toNumber(); const void *params[] = { xyz }; - return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector3D, 1, params)); + scope.result = scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector3D, 1, params)); } /*! \qmlmethod Qt::vector4d(real x, real y, real z, real w) Returns a Vector4D with the specified \c x, \c y, \c z and \c w. */ -ReturnedValue QtObject::method_vector4d(QV4::CallContext *ctx) +void QtObject::method_vector4d(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 4) - V4THROW_ERROR("Qt.vector4d(): Invalid arguments"); + if (callData->argc != 4) + THROW_GENERIC_ERROR("Qt.vector4d(): Invalid arguments"); float xyzw[4]; // qvector4d uses float internally - xyzw[0] = ctx->args()[0].toNumber(); - xyzw[1] = ctx->args()[1].toNumber(); - xyzw[2] = ctx->args()[2].toNumber(); - xyzw[3] = ctx->args()[3].toNumber(); + xyzw[0] = callData->args[0].toNumber(); + xyzw[1] = callData->args[1].toNumber(); + xyzw[2] = callData->args[2].toNumber(); + xyzw[3] = callData->args[3].toNumber(); const void *params[] = { xyzw }; - return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector4D, 1, params)); + scope.result = scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector4D, 1, params)); } /*! \qmlmethod Qt::quaternion(real scalar, real x, real y, real z) Returns a Quaternion with the specified \c scalar, \c x, \c y, and \c z. */ -ReturnedValue QtObject::method_quaternion(QV4::CallContext *ctx) +void QtObject::method_quaternion(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 4) - V4THROW_ERROR("Qt.quaternion(): Invalid arguments"); + if (callData->argc != 4) + THROW_GENERIC_ERROR("Qt.quaternion(): Invalid arguments"); qreal sxyz[4]; // qquaternion uses qreal internally - sxyz[0] = ctx->args()[0].toNumber(); - sxyz[1] = ctx->args()[1].toNumber(); - sxyz[2] = ctx->args()[2].toNumber(); - sxyz[3] = ctx->args()[3].toNumber(); + sxyz[0] = callData->args[0].toNumber(); + sxyz[1] = callData->args[1].toNumber(); + sxyz[2] = callData->args[2].toNumber(); + sxyz[3] = callData->args[3].toNumber(); const void *params[] = { sxyz }; - return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QQuaternion, 1, params)); + scope.result = scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QQuaternion, 1, params)); } /*! @@ -510,44 +516,47 @@ matrix values. Finally, the function may be called with no arguments and the resulting matrix will be the identity matrix. */ -ReturnedValue QtObject::method_matrix4x4(QV4::CallContext *ctx) +void QtObject::method_matrix4x4(const BuiltinFunction *, Scope &scope, CallData *callData) { - QV4::ExecutionEngine *v4 = ctx->d()->engine; + QV4::ExecutionEngine *v4 = scope.engine; - if (ctx->argc() == 0) - return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 0, Q_NULLPTR)); + if (callData->argc == 0) { + scope.result = scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 0, Q_NULLPTR)); + return; + } - if (ctx->argc() == 1 && ctx->args()[0].isObject()) { + if (callData->argc == 1 && callData->args[0].isObject()) { bool ok = false; - QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, QQmlV4Handle(ctx->args()[0]), v4, &ok); + QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, QQmlV4Handle(callData->args[0]), v4, &ok); if (!ok) - V4THROW_ERROR("Qt.matrix4x4(): Invalid argument: not a valid matrix4x4 values array"); - return ctx->engine()->fromVariant(v); + THROW_GENERIC_ERROR("Qt.matrix4x4(): Invalid argument: not a valid matrix4x4 values array"); + scope.result = scope.engine->fromVariant(v); + return; } - if (ctx->argc() != 16) - V4THROW_ERROR("Qt.matrix4x4(): Invalid arguments"); + if (callData->argc != 16) + THROW_GENERIC_ERROR("Qt.matrix4x4(): Invalid arguments"); qreal vals[16]; // qmatrix4x4 uses qreal internally - vals[0] = ctx->args()[0].toNumber(); - vals[1] = ctx->args()[1].toNumber(); - vals[2] = ctx->args()[2].toNumber(); - vals[3] = ctx->args()[3].toNumber(); - vals[4] = ctx->args()[4].toNumber(); - vals[5] = ctx->args()[5].toNumber(); - vals[6] = ctx->args()[6].toNumber(); - vals[7] = ctx->args()[7].toNumber(); - vals[8] = ctx->args()[8].toNumber(); - vals[9] = ctx->args()[9].toNumber(); - vals[10] = ctx->args()[10].toNumber(); - vals[11] = ctx->args()[11].toNumber(); - vals[12] = ctx->args()[12].toNumber(); - vals[13] = ctx->args()[13].toNumber(); - vals[14] = ctx->args()[14].toNumber(); - vals[15] = ctx->args()[15].toNumber(); + vals[0] = callData->args[0].toNumber(); + vals[1] = callData->args[1].toNumber(); + vals[2] = callData->args[2].toNumber(); + vals[3] = callData->args[3].toNumber(); + vals[4] = callData->args[4].toNumber(); + vals[5] = callData->args[5].toNumber(); + vals[6] = callData->args[6].toNumber(); + vals[7] = callData->args[7].toNumber(); + vals[8] = callData->args[8].toNumber(); + vals[9] = callData->args[9].toNumber(); + vals[10] = callData->args[10].toNumber(); + vals[11] = callData->args[11].toNumber(); + vals[12] = callData->args[12].toNumber(); + vals[13] = callData->args[13].toNumber(); + vals[14] = callData->args[14].toNumber(); + vals[15] = callData->args[15].toNumber(); const void *params[] = { vals }; - return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 1, params)); + scope.result = scope.engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 1, params)); } /*! @@ -564,27 +573,29 @@ by factor and converts the color back to RGB. If \c factor is not supplied, returns a color 50% lighter than \c baseColor (factor 1.5). */ -ReturnedValue QtObject::method_lighter(QV4::CallContext *ctx) +void QtObject::method_lighter(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 1 && ctx->argc() != 2) - V4THROW_ERROR("Qt.lighter(): Invalid arguments"); + if (callData->argc != 1 && callData->argc != 2) + THROW_GENERIC_ERROR("Qt.lighter(): Invalid arguments"); - QVariant v = ctx->engine()->toVariant(ctx->args()[0], -1); + QVariant v = scope.engine->toVariant(callData->args[0], -1); if (v.userType() == QVariant::String) { bool ok = false; v = QQmlStringConverters::colorFromString(v.toString(), &ok); if (!ok) { - return QV4::Encode::null(); + scope.result = QV4::Encode::null(); + return; } } else if (v.userType() != QVariant::Color) { - return QV4::Encode::null(); + scope.result = QV4::Encode::null(); + return; } qreal factor = 1.5; - if (ctx->argc() == 2) - factor = ctx->args()[1].toNumber(); + if (callData->argc == 2) + factor = callData->args[1].toNumber(); - return ctx->engine()->fromVariant(QQml_colorProvider()->lighter(v, factor)); + scope.result = scope.engine->fromVariant(QQml_colorProvider()->lighter(v, factor)); } /*! @@ -602,27 +613,29 @@ by factor and converts the color back to RGB. If \c factor is not supplied, returns a color 50% darker than \c baseColor (factor 2.0). */ -ReturnedValue QtObject::method_darker(QV4::CallContext *ctx) +void QtObject::method_darker(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 1 && ctx->argc() != 2) - V4THROW_ERROR("Qt.darker(): Invalid arguments"); + if (callData->argc != 1 && callData->argc != 2) + THROW_GENERIC_ERROR("Qt.darker(): Invalid arguments"); - QVariant v = ctx->engine()->toVariant(ctx->args()[0], -1); + QVariant v = scope.engine->toVariant(callData->args[0], -1); if (v.userType() == QVariant::String) { bool ok = false; v = QQmlStringConverters::colorFromString(v.toString(), &ok); if (!ok) { - return QV4::Encode::null(); + scope.result = QV4::Encode::null(); + return; } } else if (v.userType() != QVariant::Color) { - return QV4::Encode::null(); + scope.result = QV4::Encode::null(); + return; } qreal factor = 2.0; - if (ctx->argc() == 2) - factor = ctx->args()[1].toNumber(); + if (callData->argc == 2) + factor = callData->args[1].toNumber(); - return ctx->engine()->fromVariant(QQml_colorProvider()->darker(v, factor)); + scope.result = scope.engine->fromVariant(QQml_colorProvider()->darker(v, factor)); } /*! @@ -649,36 +662,40 @@ ReturnedValue QtObject::method_darker(QV4::CallContext *ctx) Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color. */ -ReturnedValue QtObject::method_tint(QV4::CallContext *ctx) +void QtObject::method_tint(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 2) - V4THROW_ERROR("Qt.tint(): Invalid arguments"); + if (callData->argc != 2) + THROW_GENERIC_ERROR("Qt.tint(): Invalid arguments"); // base color - QVariant v1 = ctx->engine()->toVariant(ctx->args()[0], -1); + QVariant v1 = scope.engine->toVariant(callData->args[0], -1); if (v1.userType() == QVariant::String) { bool ok = false; v1 = QQmlStringConverters::colorFromString(v1.toString(), &ok); if (!ok) { - return QV4::Encode::null(); + scope.result = QV4::Encode::null(); + return; } } else if (v1.userType() != QVariant::Color) { - return QV4::Encode::null(); + scope.result = QV4::Encode::null(); + return; } // tint color - QVariant v2 = ctx->engine()->toVariant(ctx->args()[1], -1); + QVariant v2 = scope.engine->toVariant(callData->args[1], -1); if (v2.userType() == QVariant::String) { bool ok = false; v2 = QQmlStringConverters::colorFromString(v2.toString(), &ok); if (!ok) { - return QV4::Encode::null(); + scope.result = QV4::Encode::null(); + return; } } else if (v2.userType() != QVariant::Color) { - return QV4::Encode::null(); + scope.result = QV4::Encode::null(); + return; } - return ctx->engine()->fromVariant(QQml_colorProvider()->tint(v1, v2)); + scope.result = scope.engine->fromVariant(QQml_colorProvider()->tint(v1, v2)); } /*! @@ -697,32 +714,31 @@ If \a format is not specified, \a date is formatted using \sa Locale */ -ReturnedValue QtObject::method_formatDate(QV4::CallContext *ctx) +void QtObject::method_formatDate(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() < 1 || ctx->argc() > 2) - V4THROW_ERROR("Qt.formatDate(): Invalid arguments"); - QV4::Scope scope(ctx); + if (callData->argc < 1 || callData->argc > 2) + THROW_GENERIC_ERROR("Qt.formatDate(): Invalid arguments"); Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; - QDate date = ctx->engine()->toVariant(ctx->args()[0], -1).toDateTime().date(); + QDate date = scope.engine->toVariant(callData->args[0], -1).toDateTime().date(); QString formattedDate; - if (ctx->argc() == 2) { - QV4::ScopedString s(scope, ctx->args()[1]); + if (callData->argc == 2) { + QV4::ScopedString s(scope, callData->args[1]); if (s) { QString format = s->toQString(); formattedDate = date.toString(format); - } else if (ctx->args()[1].isNumber()) { - quint32 intFormat = ctx->args()[1].asDouble(); + } else if (callData->args[1].isNumber()) { + quint32 intFormat = callData->args[1].asDouble(); Qt::DateFormat format = Qt::DateFormat(intFormat); formattedDate = date.toString(format); } else { - V4THROW_ERROR("Qt.formatDate(): Invalid date format"); + THROW_GENERIC_ERROR("Qt.formatDate(): Invalid date format"); } } else { formattedDate = date.toString(enumFormat); } - return ctx->d()->engine->newString(formattedDate)->asReturnedValue(); + scope.result = scope.engine->newString(formattedDate); } /*! @@ -740,38 +756,37 @@ If \a format is not specified, \a time is formatted using \sa Locale */ -ReturnedValue QtObject::method_formatTime(QV4::CallContext *ctx) +void QtObject::method_formatTime(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() < 1 || ctx->argc() > 2) - V4THROW_ERROR("Qt.formatTime(): Invalid arguments"); - QV4::Scope scope(ctx); + if (callData->argc < 1 || callData->argc > 2) + THROW_GENERIC_ERROR("Qt.formatTime(): Invalid arguments"); - QVariant argVariant = ctx->engine()->toVariant(ctx->args()[0], -1); + QVariant argVariant = scope.engine->toVariant(callData->args[0], -1); QTime time; - if (ctx->args()[0].as() || (argVariant.type() == QVariant::String)) + if (callData->args[0].as() || (argVariant.type() == QVariant::String)) time = argVariant.toDateTime().time(); else // if (argVariant.type() == QVariant::Time), or invalid. time = argVariant.toTime(); Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; QString formattedTime; - if (ctx->argc() == 2) { - QV4::ScopedString s(scope, ctx->args()[1]); + if (callData->argc == 2) { + QV4::ScopedString s(scope, callData->args[1]); if (s) { QString format = s->toQString(); formattedTime = time.toString(format); - } else if (ctx->args()[1].isNumber()) { - quint32 intFormat = ctx->args()[1].asDouble(); + } else if (callData->args[1].isNumber()) { + quint32 intFormat = callData->args[1].asDouble(); Qt::DateFormat format = Qt::DateFormat(intFormat); formattedTime = time.toString(format); } else { - V4THROW_ERROR("Qt.formatTime(): Invalid time format"); + THROW_GENERIC_ERROR("Qt.formatTime(): Invalid time format"); } } else { formattedTime = time.toString(enumFormat); } - return ctx->d()->engine->newString(formattedTime)->asReturnedValue(); + scope.result = scope.engine->newString(formattedTime); } /*! @@ -864,32 +879,31 @@ with the \a format values below to produce the following results: \sa Locale */ -ReturnedValue QtObject::method_formatDateTime(QV4::CallContext *ctx) +void QtObject::method_formatDateTime(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() < 1 || ctx->argc() > 2) - V4THROW_ERROR("Qt.formatDateTime(): Invalid arguments"); - QV4::Scope scope(ctx); + if (callData->argc < 1 || callData->argc > 2) + THROW_GENERIC_ERROR("Qt.formatDateTime(): Invalid arguments"); Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; - QDateTime dt = ctx->engine()->toVariant(ctx->args()[0], -1).toDateTime(); + QDateTime dt = scope.engine->toVariant(callData->args[0], -1).toDateTime(); QString formattedDt; - if (ctx->argc() == 2) { - QV4::ScopedString s(scope, ctx->args()[1]); + if (callData->argc == 2) { + QV4::ScopedString s(scope, callData->args[1]); if (s) { QString format = s->toQString(); formattedDt = dt.toString(format); - } else if (ctx->args()[1].isNumber()) { - quint32 intFormat = ctx->args()[1].asDouble(); + } else if (callData->args[1].isNumber()) { + quint32 intFormat = callData->args[1].asDouble(); Qt::DateFormat format = Qt::DateFormat(intFormat); formattedDt = dt.toString(format); } else { - V4THROW_ERROR("Qt.formatDateTime(): Invalid datetime format"); + THROW_GENERIC_ERROR("Qt.formatDateTime(): Invalid datetime format"); } } else { formattedDt = dt.toString(enumFormat); } - return ctx->d()->engine->newString(formattedDt)->asReturnedValue(); + scope.result = scope.engine->newString(formattedDt); } /*! @@ -903,90 +917,94 @@ ReturnedValue QtObject::method_formatDateTime(QV4::CallContext *ctx) still fail to launch or fail to open the requested URL. This result will not be reported back to the application. */ -ReturnedValue QtObject::method_openUrlExternally(QV4::CallContext *ctx) +void QtObject::method_openUrlExternally(const BuiltinFunction *b, Scope &scope, CallData *callData) { - if (ctx->argc() != 1) - return QV4::Encode(false); + if (callData->argc != 1) { + scope.result = QV4::Encode(false); + return; + } - QUrl url(Value::fromReturnedValue(method_resolvedUrl(ctx)).toQStringNoThrow()); - return ctx->engine()->fromVariant(QQml_guiProvider()->openUrlExternally(url)); + method_resolvedUrl(b, scope, callData); + QUrl url(scope.result.toQStringNoThrow()); + scope.result = scope.engine->fromVariant(QQml_guiProvider()->openUrlExternally(url)); } /*! \qmlmethod url Qt::resolvedUrl(url url) Returns \a url resolved relative to the URL of the caller. */ -ReturnedValue QtObject::method_resolvedUrl(QV4::CallContext *ctx) +void QtObject::method_resolvedUrl(const BuiltinFunction *, Scope &scope, CallData *callData) { - ExecutionEngine *v4 = ctx->engine(); + ExecutionEngine *v4 = scope.engine; - QUrl url = v4->toVariant(ctx->args()[0], -1).toUrl(); + QUrl url = v4->toVariant(callData->args[0], -1).toUrl(); QQmlEngine *e = v4->qmlEngine(); QQmlEnginePrivate *p = 0; if (e) p = QQmlEnginePrivate::get(e); if (p) { QQmlContextData *ctxt = v4->callingQmlContext(); if (ctxt) - return v4->newString(ctxt->resolvedUrl(url).toString())->asReturnedValue(); + scope.result = v4->newString(ctxt->resolvedUrl(url).toString()); else - return v4->newString(url.toString())->asReturnedValue(); + scope.result = v4->newString(url.toString()); + return; } - return v4->newString(e->baseUrl().resolved(url).toString())->asReturnedValue(); + scope.result = v4->newString(e->baseUrl().resolved(url).toString()); } /*! \qmlmethod list Qt::fontFamilies() Returns a list of the font families available to the application. */ -ReturnedValue QtObject::method_fontFamilies(CallContext *ctx) +void QtObject::method_fontFamilies(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 0) - V4THROW_ERROR("Qt.fontFamilies(): Invalid arguments"); + if (callData->argc != 0) + THROW_GENERIC_ERROR("Qt.fontFamilies(): Invalid arguments"); - return ctx->engine()->fromVariant(QVariant(QQml_guiProvider()->fontFamilies())); + scope.result = scope.engine->fromVariant(QVariant(QQml_guiProvider()->fontFamilies())); } /*! \qmlmethod string Qt::md5(data) Returns a hex string of the md5 hash of \c data. */ -ReturnedValue QtObject::method_md5(CallContext *ctx) +void QtObject::method_md5(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 1) - V4THROW_ERROR("Qt.md5(): Invalid arguments"); + if (callData->argc != 1) + THROW_GENERIC_ERROR("Qt.md5(): Invalid arguments"); - QByteArray data = ctx->args()[0].toQStringNoThrow().toUtf8(); + QByteArray data = callData->args[0].toQStringNoThrow().toUtf8(); QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5); - return ctx->d()->engine->newString(QLatin1String(result.toHex()))->asReturnedValue(); + scope.result = scope.engine->newString(QLatin1String(result.toHex())); } /*! \qmlmethod string Qt::btoa(data) Binary to ASCII - this function returns a base64 encoding of \c data. */ -ReturnedValue QtObject::method_btoa(CallContext *ctx) +void QtObject::method_btoa(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 1) - V4THROW_ERROR("Qt.btoa(): Invalid arguments"); + if (callData->argc != 1) + THROW_GENERIC_ERROR("Qt.btoa(): Invalid arguments"); - QByteArray data = ctx->args()[0].toQStringNoThrow().toUtf8(); + QByteArray data = callData->args[0].toQStringNoThrow().toUtf8(); - return ctx->d()->engine->newString(QLatin1String(data.toBase64()))->asReturnedValue(); + scope.result = scope.engine->newString(QLatin1String(data.toBase64())); } /*! \qmlmethod string Qt::atob(data) ASCII to binary - this function decodes the base64 encoded \a data string and returns it. */ -ReturnedValue QtObject::method_atob(CallContext *ctx) +void QtObject::method_atob(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 1) - V4THROW_ERROR("Qt.atob(): Invalid arguments"); + if (callData->argc != 1) + THROW_GENERIC_ERROR("Qt.atob(): Invalid arguments"); - QByteArray data = ctx->args()[0].toQStringNoThrow().toLatin1(); + QByteArray data = callData->args[0].toQStringNoThrow().toLatin1(); - return ctx->d()->engine->newString(QString::fromUtf8(QByteArray::fromBase64(data)))->asReturnedValue(); + scope.result = scope.engine->newString(QString::fromUtf8(QByteArray::fromBase64(data))); } /*! @@ -998,10 +1016,10 @@ QQmlEngine::quit() signal to the QCoreApplication::quit() slot. \sa exit() */ -ReturnedValue QtObject::method_quit(CallContext *ctx) +void QtObject::method_quit(const BuiltinFunction *, Scope &scope, CallData *) { - QQmlEnginePrivate::get(ctx->engine()->qmlEngine())->sendQuit(); - return QV4::Encode::undefined(); + QQmlEnginePrivate::get(scope.engine->qmlEngine())->sendQuit(); + scope.result = Encode::undefined(); } /*! @@ -1015,15 +1033,15 @@ ReturnedValue QtObject::method_quit(CallContext *ctx) \sa quit() */ -ReturnedValue QtObject::method_exit(CallContext *ctx) +void QtObject::method_exit(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 1) - V4THROW_ERROR("Qt.exit(): Invalid arguments"); + if (callData->argc != 1) + THROW_GENERIC_ERROR("Qt.exit(): Invalid arguments"); - int retCode = ctx->args()[0].toNumber(); + int retCode = callData->args[0].toNumber(); - QQmlEnginePrivate::get(ctx->engine()->qmlEngine())->sendExit(retCode); - return QV4::Encode::undefined(); + QQmlEnginePrivate::get(scope.engine->qmlEngine())->sendExit(retCode); + scope.result = QV4::Encode::undefined(); } /*! @@ -1050,11 +1068,10 @@ If this is the case, consider using \l{QtQml::Qt::createComponent()}{Qt.createCo See \l {Dynamic QML Object Creation from JavaScript} for more information on using this function. */ -ReturnedValue QtObject::method_createQmlObject(CallContext *ctx) +void QtObject::method_createQmlObject(const BuiltinFunction *, Scope &scope, CallData *callData) { - Scope scope(ctx); - if (ctx->argc() < 2 || ctx->argc() > 3) - V4THROW_ERROR("Qt.createQmlObject(): Invalid arguments"); + if (callData->argc < 2 || callData->argc > 3) + THROW_GENERIC_ERROR("Qt.createQmlObject(): Invalid arguments"); struct Error { static ReturnedValue create(QV4::ExecutionEngine *v4, const QList &errors) { @@ -1085,7 +1102,7 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx) } }; - QV8Engine *v8engine = ctx->d()->engine->v8Engine; + QV8Engine *v8engine = scope.engine->v8Engine; QQmlEngine *engine = v8engine->engine(); QQmlContextData *context = scope.engine->callingQmlContext(); @@ -1097,13 +1114,13 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx) effectiveContext = context->asQQmlContext(); Q_ASSERT(effectiveContext); - QString qml = ctx->args()[0].toQStringNoThrow(); + QString qml = callData->args[0].toQStringNoThrow(); if (qml.isEmpty()) - return QV4::Encode::null(); + RETURN_RESULT(Encode::null()); QUrl url; - if (ctx->argc() > 2) - url = QUrl(ctx->args()[2].toQStringNoThrow()); + if (callData->argc > 2) + url = QUrl(callData->args[2].toQStringNoThrow()); else url = QUrl(QLatin1String("inline")); @@ -1111,11 +1128,11 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx) url = context->resolvedUrl(url); QObject *parentArg = 0; - QV4::Scoped qobjectWrapper(scope, ctx->args()[1]); + QV4::Scoped qobjectWrapper(scope, callData->args[1]); if (!!qobjectWrapper) parentArg = qobjectWrapper->object(); if (!parentArg) - V4THROW_ERROR("Qt.createQmlObject(): Missing parent object"); + THROW_GENERIC_ERROR("Qt.createQmlObject(): Missing parent object"); QQmlTypeData *typeData = QQmlEnginePrivate::get(engine)->typeLoader.getType( qml.toUtf8(), url, QQmlTypeLoader::Synchronous); @@ -1126,12 +1143,12 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx) componentPrivate->progress = 1.0; if (component.isError()) { - ScopedValue v(scope, Error::create(ctx->d()->engine, component.errors())); - return ctx->engine()->throwError(v); + ScopedValue v(scope, Error::create(scope.engine, component.errors())); + RETURN_RESULT(scope.engine->throwError(v)); } if (!component.isReady()) - V4THROW_ERROR("Qt.createQmlObject(): Component is not ready"); + THROW_GENERIC_ERROR("Qt.createQmlObject(): Component is not ready"); QObject *obj = component.beginCreate(effectiveContext); if (obj) { @@ -1150,13 +1167,14 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx) component.completeCreate(); if (component.isError()) { - ScopedValue v(scope, Error::create(ctx->d()->engine, component.errors())); - return ctx->engine()->throwError(v); + ScopedValue v(scope, Error::create(scope.engine, component.errors())); + scope.result = scope.engine->throwError(v); + return; } Q_ASSERT(obj); - return QV4::QObjectWrapper::wrap(ctx->d()->engine, obj); + scope.result = QV4::QObjectWrapper::wrap(scope.engine, obj); } /*! @@ -1203,14 +1221,12 @@ See \l {Dynamic QML Object Creation from JavaScript} for more information on usi To create a QML object from an arbitrary string of QML (instead of a file), use \l{QtQml::Qt::createQmlObject()}{Qt.createQmlObject()}. */ -ReturnedValue QtObject::method_createComponent(CallContext *ctx) +void QtObject::method_createComponent(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() < 1 || ctx->argc() > 3) - return ctx->engine()->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments")); + if (callData->argc < 1 || callData->argc > 3) + THROW_GENERIC_ERROR("Qt.createComponent(): Invalid arguments"); - Scope scope(ctx); - - QV8Engine *v8engine = ctx->d()->engine->v8Engine; + QV8Engine *v8engine = scope.engine->v8Engine; QQmlEngine *engine = v8engine->engine(); QQmlContextData *context = scope.engine->callingQmlContext(); @@ -1219,41 +1235,41 @@ ReturnedValue QtObject::method_createComponent(CallContext *ctx) if (context->isPragmaLibraryContext) effectiveContext = 0; - QString arg = ctx->args()[0].toQStringNoThrow(); + QString arg = callData->args[0].toQStringNoThrow(); if (arg.isEmpty()) - return QV4::Encode::null(); + RETURN_RESULT(QV4::Encode::null()); QQmlComponent::CompilationMode compileMode = QQmlComponent::PreferSynchronous; QObject *parentArg = 0; int consumedCount = 1; - if (ctx->argc() > 1) { - ScopedValue lastArg(scope, ctx->args()[ctx->argc()-1]); + if (callData->argc > 1) { + ScopedValue lastArg(scope, callData->args[callData->argc-1]); // The second argument could be the mode enum - if (ctx->args()[1].isInteger()) { - int mode = ctx->args()[1].integerValue(); + if (callData->args[1].isInteger()) { + int mode = callData->args[1].integerValue(); if (mode != int(QQmlComponent::PreferSynchronous) && mode != int(QQmlComponent::Asynchronous)) - return ctx->engine()->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments")); + THROW_GENERIC_ERROR("Qt.createComponent(): Invalid arguments"); compileMode = QQmlComponent::CompilationMode(mode); consumedCount += 1; } else { // The second argument could be the parent only if there are exactly two args - if ((ctx->argc() != 2) || !(lastArg->isObject() || lastArg->isNull())) - return ctx->engine()->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments")); + if ((callData->argc != 2) || !(lastArg->isObject() || lastArg->isNull())) + THROW_GENERIC_ERROR("Qt.createComponent(): Invalid arguments"); } - if (consumedCount < ctx->argc()) { + if (consumedCount < callData->argc) { if (lastArg->isObject()) { Scoped qobjectWrapper(scope, lastArg); if (qobjectWrapper) parentArg = qobjectWrapper->object(); if (!parentArg) - return ctx->engine()->throwError(QStringLiteral("Qt.createComponent(): Invalid parent object")); + THROW_GENERIC_ERROR("Qt.createComponent(): Invalid parent object"); } else if (lastArg->isNull()) { parentArg = 0; } else { - return ctx->engine()->throwError(QStringLiteral("Qt.createComponent(): Invalid parent object")); + THROW_GENERIC_ERROR("Qt.createComponent(): Invalid parent object"); } } } @@ -1264,7 +1280,7 @@ ReturnedValue QtObject::method_createComponent(CallContext *ctx) QQmlData::get(c, true)->explicitIndestructibleSet = false; QQmlData::get(c)->indestructible = false; - return QV4::QObjectWrapper::wrap(ctx->d()->engine, c); + scope.result = QV4::QObjectWrapper::wrap(scope.engine, c); } /*! @@ -1287,18 +1303,18 @@ ReturnedValue QtObject::method_createComponent(CallContext *ctx) \sa Locale */ -ReturnedValue QtObject::method_locale(CallContext *ctx) +void QtObject::method_locale(const BuiltinFunction *, Scope &scope, CallData *callData) { QString code; - if (ctx->argc() > 1) - V4THROW_ERROR("locale() requires 0 or 1 argument"); - if (ctx->argc() == 1 && !ctx->args()[0].isString()) - V4THROW_TYPE("locale(): argument (locale code) must be a string"); + if (callData->argc > 1) + THROW_GENERIC_ERROR("locale() requires 0 or 1 argument"); + if (callData->argc == 1 && !callData->args[0].isString()) + THROW_TYPE_ERROR_WITH_MESSAGE("locale(): argument (locale code) must be a string"); - if (ctx->argc() == 1) - code = ctx->args()[0].toQStringNoThrow(); + if (callData->argc == 1) + code = callData->args[0].toQStringNoThrow(); - return QQmlLocale::locale(ctx->engine(), code); + scope.result = QQmlLocale::locale(scope.engine, code); } void Heap::QQmlBindingFunction::init(const QV4::FunctionObject *originalFunction) @@ -1360,62 +1376,62 @@ DEFINE_OBJECT_VTABLE(QQmlBindingFunction); \since 5.0 */ -ReturnedValue QtObject::method_binding(CallContext *ctx) +void QtObject::method_binding(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 1) - V4THROW_ERROR("binding() requires 1 argument"); - const QV4::FunctionObject *f = ctx->args()[0].as(); + if (callData->argc != 1) + THROW_GENERIC_ERROR("binding() requires 1 argument"); + const QV4::FunctionObject *f = callData->args[0].as(); if (!f) - V4THROW_TYPE("binding(): argument (binding expression) must be a function"); + THROW_TYPE_ERROR_WITH_MESSAGE("binding(): argument (binding expression) must be a function"); - return (ctx->d()->engine->memoryManager->allocObject(f))->asReturnedValue(); + scope.result = scope.engine->memoryManager->allocObject(f); } -ReturnedValue QtObject::method_get_platform(CallContext *ctx) +void QtObject::method_get_platform(const BuiltinFunction *, Scope &scope, CallData *callData) { // ### inefficient. Should be just a value based getter - Object *o = ctx->thisObject().as(); + Object *o = callData->thisObject.as(); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); QtObject *qt = o->as(); if (!qt) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); if (!qt->d()->platform) // Only allocate a platform object once - qt->d()->platform = new QQmlPlatform(ctx->d()->engine->jsEngine()); + qt->d()->platform = new QQmlPlatform(scope.engine->jsEngine()); - return QV4::QObjectWrapper::wrap(ctx->d()->engine, qt->d()->platform); + scope.result = QV4::QObjectWrapper::wrap(scope.engine, qt->d()->platform); } -ReturnedValue QtObject::method_get_application(CallContext *ctx) +void QtObject::method_get_application(const BuiltinFunction *, Scope &scope, CallData *callData) { // ### inefficient. Should be just a value based getter - Object *o = ctx->thisObject().as(); + Object *o = callData->thisObject.as(); if (!o) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); QtObject *qt = o->as(); if (!qt) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); if (!qt->d()->application) // Only allocate an application object once - qt->d()->application = QQml_guiProvider()->application(ctx->d()->engine->jsEngine()); + qt->d()->application = QQml_guiProvider()->application(scope.engine->jsEngine()); - return QV4::QObjectWrapper::wrap(ctx->d()->engine, qt->d()->application); + scope.result = QV4::QObjectWrapper::wrap(scope.engine, qt->d()->application); } -ReturnedValue QtObject::method_get_inputMethod(CallContext *ctx) +void QtObject::method_get_inputMethod(const BuiltinFunction *, Scope &scope, CallData *) { QObject *o = QQml_guiProvider()->inputMethod(); - return QV4::QObjectWrapper::wrap(ctx->d()->engine, o); + scope.result = QV4::QObjectWrapper::wrap(scope.engine, o); } -ReturnedValue QtObject::method_get_styleHints(CallContext *ctx) +void QtObject::method_get_styleHints(const BuiltinFunction *, Scope &scope, CallData *) { QObject *o = QQml_guiProvider()->styleHints(); - return QV4::QObjectWrapper::wrap(ctx->d()->engine, o); + scope.result = QV4::QObjectWrapper::wrap(scope.engine, o); } @@ -1475,35 +1491,35 @@ static QString jsStack(QV4::ExecutionEngine *engine) { return stack; } -static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *ctx, - bool printStack = false) +static void writeToConsole(const BuiltinFunction *, Scope &scope, CallData *callData, + ConsoleLogTypes logType, bool printStack = false) { QLoggingCategory *loggingCategory = 0; QString result; - QV4::ExecutionEngine *v4 = ctx->d()->engine; + QV4::ExecutionEngine *v4 = scope.engine; int start = 0; - if (ctx->argc() > 0) { - if (const QObjectWrapper* wrapper = ctx->args()[0].as()) { + if (callData->argc > 0) { + if (const QObjectWrapper* wrapper = callData->args[0].as()) { if (QQmlLoggingCategory* category = qobject_cast(wrapper->object())) { if (category->category()) loggingCategory = category->category(); else - V4THROW_ERROR("A QmlLoggingCatgory was provided without a valid name"); + THROW_GENERIC_ERROR("A QmlLoggingCatgory was provided without a valid name"); start = 1; } } } - for (int i = start; i < ctx->argc(); ++i) { + for (int i = start; i < callData->argc; ++i) { if (i != start) result.append(QLatin1Char(' ')); - if (ctx->args()[i].as()) - result += QLatin1Char('[') + ctx->args()[i].toQStringNoThrow() + QLatin1Char(']'); + if (callData->args[i].as()) + result += QLatin1Char('[') + callData->args[i].toQStringNoThrow() + QLatin1Char(']'); else - result.append(ctx->args()[i].toQStringNoThrow()); + result.append(callData->args[i].toQStringNoThrow()); } if (printStack) @@ -1540,32 +1556,32 @@ static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *c break; } - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } DEFINE_OBJECT_VTABLE(ConsoleObject); -QV4::ReturnedValue ConsoleObject::method_error(CallContext *ctx) +void ConsoleObject::method_error(const BuiltinFunction *b, Scope &scope, CallData *callData) { - return writeToConsole(Error, ctx); + writeToConsole(b, scope, callData, Error); } -QV4::ReturnedValue ConsoleObject::method_log(CallContext *ctx) +void ConsoleObject::method_log(const BuiltinFunction *b, Scope &scope, CallData *callData) { //console.log //console.debug //print - return writeToConsole(Log, ctx); + writeToConsole(b, scope, callData, Log); } -QV4::ReturnedValue ConsoleObject::method_info(CallContext *ctx) +void ConsoleObject::method_info(const BuiltinFunction *b, Scope &scope, CallData *callData) { - return writeToConsole(Info, ctx); + writeToConsole(b, scope, callData, Info); } -QV4::ReturnedValue ConsoleObject::method_profile(CallContext *ctx) +void ConsoleObject::method_profile(const BuiltinFunction *, Scope &scope, CallData *) { - QV4::ExecutionEngine *v4 = ctx->d()->engine; + QV4::ExecutionEngine *v4 = scope.engine; QV4::StackFrame frame = v4->currentStackFrame(); const QByteArray baSource = frame.source.toUtf8(); @@ -1579,12 +1595,12 @@ QV4::ReturnedValue ConsoleObject::method_profile(CallContext *ctx) logger.debug("Profiling started."); } - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } -QV4::ReturnedValue ConsoleObject::method_profileEnd(CallContext *ctx) +void ConsoleObject::method_profileEnd(const BuiltinFunction *, Scope &scope, CallData *) { - QV4::ExecutionEngine *v4 = ctx->d()->engine; + QV4::ExecutionEngine *v4 = scope.engine; QV4::StackFrame frame = v4->currentStackFrame(); const QByteArray baSource = frame.source.toUtf8(); @@ -1599,46 +1615,46 @@ QV4::ReturnedValue ConsoleObject::method_profileEnd(CallContext *ctx) logger.debug("Profiling ended."); } - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } -QV4::ReturnedValue ConsoleObject::method_time(CallContext *ctx) +void ConsoleObject::method_time(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 1) - V4THROW_ERROR("console.time(): Invalid arguments"); + if (callData->argc != 1) + THROW_GENERIC_ERROR("console.time(): Invalid arguments"); - QV8Engine *v8engine = ctx->d()->engine->v8Engine; + QV8Engine *v8engine = scope.engine->v8Engine; - QString name = ctx->args()[0].toQStringNoThrow(); + QString name = callData->args[0].toQStringNoThrow(); v8engine->startTimer(name); - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } -QV4::ReturnedValue ConsoleObject::method_timeEnd(CallContext *ctx) +void ConsoleObject::method_timeEnd(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 1) - V4THROW_ERROR("console.timeEnd(): Invalid arguments"); + if (callData->argc != 1) + THROW_GENERIC_ERROR("console.timeEnd(): Invalid arguments"); - QV8Engine *v8engine = ctx->d()->engine->v8Engine; + QV8Engine *v8engine = scope.engine->v8Engine; - QString name = ctx->args()[0].toQStringNoThrow(); + QString name = callData->args[0].toQStringNoThrow(); bool wasRunning; qint64 elapsed = v8engine->stopTimer(name, &wasRunning); if (wasRunning) { qDebug("%s: %llims", qPrintable(name), elapsed); } - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } -QV4::ReturnedValue ConsoleObject::method_count(CallContext *ctx) +void ConsoleObject::method_count(const BuiltinFunction *, Scope &scope, CallData *callData) { // first argument: name to print. Ignore any additional arguments QString name; - if (ctx->argc() > 0) - name = ctx->args()[0].toQStringNoThrow(); + if (callData->argc > 0) + name = callData->args[0].toQStringNoThrow(); - QV4::ExecutionEngine *v4 = ctx->d()->engine; - QV8Engine *v8engine = ctx->d()->engine->v8Engine; + QV4::ExecutionEngine *v4 = scope.engine; + QV8Engine *v8engine = scope.engine->v8Engine; QV4::StackFrame frame = v4->currentStackFrame(); @@ -1651,15 +1667,15 @@ QV4::ReturnedValue ConsoleObject::method_count(CallContext *ctx) qPrintable(frame.function)) .debug("%s", qPrintable(message)); - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } -QV4::ReturnedValue ConsoleObject::method_trace(CallContext *ctx) +void ConsoleObject::method_trace(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 0) - V4THROW_ERROR("console.trace(): Invalid arguments"); + if (callData->argc != 0) + THROW_GENERIC_ERROR("console.trace(): Invalid arguments"); - QV4::ExecutionEngine *v4 = ctx->d()->engine; + QV4::ExecutionEngine *v4 = scope.engine; QString stack = jsStack(v4); @@ -1668,28 +1684,28 @@ QV4::ReturnedValue ConsoleObject::method_trace(CallContext *ctx) frame.function.toUtf8().constData()) .debug("%s", qPrintable(stack)); - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } -QV4::ReturnedValue ConsoleObject::method_warn(CallContext *ctx) +void ConsoleObject::method_warn(const BuiltinFunction *b, Scope &scope, CallData *callData) { - return writeToConsole(Warn, ctx); + return writeToConsole(b, scope, callData, Warn); } -QV4::ReturnedValue ConsoleObject::method_assert(CallContext *ctx) +void ConsoleObject::method_assert(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() == 0) - V4THROW_ERROR("console.assert(): Missing argument"); + if (callData->argc == 0) + THROW_GENERIC_ERROR("console.assert(): Missing argument"); - QV4::ExecutionEngine *v4 = ctx->d()->engine; + QV4::ExecutionEngine *v4 = scope.engine; - if (!ctx->args()[0].toBoolean()) { + if (!callData->args[0].toBoolean()) { QString message; - for (int i = 1; i < ctx->argc(); ++i) { + for (int i = 1; i < callData->argc; ++i) { if (i != 1) message.append(QLatin1Char(' ')); - message.append(ctx->args()[i].toQStringNoThrow()); + message.append(callData->args[i].toQStringNoThrow()); } QString stack = jsStack(v4); @@ -1700,17 +1716,17 @@ QV4::ReturnedValue ConsoleObject::method_assert(CallContext *ctx) .critical("%s\n%s",qPrintable(message), qPrintable(stack)); } - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } -QV4::ReturnedValue ConsoleObject::method_exception(CallContext *ctx) +void ConsoleObject::method_exception(const BuiltinFunction *b, Scope &scope, CallData *callData) { - if (ctx->argc() == 0) - V4THROW_ERROR("console.exception(): Missing argument"); + if (callData->argc == 0) + THROW_GENERIC_ERROR("console.exception(): Missing argument"); - writeToConsole(Error, ctx, true); + writeToConsole(b, scope, callData, Error, true); - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } @@ -1766,38 +1782,38 @@ void QV4::GlobalExtensions::init(Object *globalObject, QJSEngine::Extensions ext \sa {Internationalization and Localization with Qt Quick} */ -ReturnedValue GlobalExtensions::method_qsTranslate(CallContext *ctx) -{ - if (ctx->argc() < 2) - V4THROW_ERROR("qsTranslate() requires at least two arguments"); - if (!ctx->args()[0].isString()) - V4THROW_ERROR("qsTranslate(): first argument (context) must be a string"); - if (!ctx->args()[1].isString()) - V4THROW_ERROR("qsTranslate(): second argument (sourceText) must be a string"); - if ((ctx->argc() > 2) && !ctx->args()[2].isString()) - V4THROW_ERROR("qsTranslate(): third argument (disambiguation) must be a string"); - - QString context = ctx->args()[0].toQStringNoThrow(); - QString text = ctx->args()[1].toQStringNoThrow(); +void GlobalExtensions::method_qsTranslate(const BuiltinFunction *, Scope &scope, CallData *callData) +{ + if (callData->argc < 2) + THROW_GENERIC_ERROR("qsTranslate() requires at least two arguments"); + if (!callData->args[0].isString()) + THROW_GENERIC_ERROR("qsTranslate(): first argument (context) must be a string"); + if (!callData->args[1].isString()) + THROW_GENERIC_ERROR("qsTranslate(): second argument (sourceText) must be a string"); + if ((callData->argc > 2) && !callData->args[2].isString()) + THROW_GENERIC_ERROR("qsTranslate(): third argument (disambiguation) must be a string"); + + QString context = callData->args[0].toQStringNoThrow(); + QString text = callData->args[1].toQStringNoThrow(); QString comment; - if (ctx->argc() > 2) comment = ctx->args()[2].toQStringNoThrow(); + if (callData->argc > 2) comment = callData->args[2].toQStringNoThrow(); int i = 3; - if (ctx->argc() > i && ctx->args()[i].isString()) { + if (callData->argc > i && callData->args[i].isString()) { qWarning("qsTranslate(): specifying the encoding as fourth argument is deprecated"); ++i; } int n = -1; - if (ctx->argc() > i) - n = ctx->args()[i].toInt32(); + if (callData->argc > i) + n = callData->args[i].toInt32(); QString result = QCoreApplication::translate(context.toUtf8().constData(), text.toUtf8().constData(), comment.toUtf8().constData(), n); - return ctx->d()->engine->newString(result)->asReturnedValue(); + scope.result = scope.engine->newString(result); } /*! @@ -1822,11 +1838,12 @@ ReturnedValue GlobalExtensions::method_qsTranslate(CallContext *ctx) \sa {Internationalization and Localization with Qt Quick} */ -ReturnedValue GlobalExtensions::method_qsTranslateNoOp(CallContext *ctx) +void GlobalExtensions::method_qsTranslateNoOp(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() < 2) - return QV4::Encode::undefined(); - return ctx->args()[1].asReturnedValue(); + if (callData->argc < 2) + scope.result = QV4::Encode::undefined(); + else + scope.result = callData->args[1]; } /*! @@ -1846,18 +1863,17 @@ ReturnedValue GlobalExtensions::method_qsTranslateNoOp(CallContext *ctx) \sa {Internationalization and Localization with Qt Quick} */ -ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx) -{ - if (ctx->argc() < 1) - V4THROW_ERROR("qsTr() requires at least one argument"); - if (!ctx->args()[0].isString()) - V4THROW_ERROR("qsTr(): first argument (sourceText) must be a string"); - if ((ctx->argc() > 1) && !ctx->args()[1].isString()) - V4THROW_ERROR("qsTr(): second argument (disambiguation) must be a string"); - if ((ctx->argc() > 2) && !ctx->args()[2].isNumber()) - V4THROW_ERROR("qsTr(): third argument (n) must be a number"); - - Scope scope(ctx); +void GlobalExtensions::method_qsTr(const BuiltinFunction *, Scope &scope, CallData *callData) +{ + if (callData->argc < 1) + THROW_GENERIC_ERROR("qsTr() requires at least one argument"); + if (!callData->args[0].isString()) + THROW_GENERIC_ERROR("qsTr(): first argument (sourceText) must be a string"); + if ((callData->argc > 1) && !callData->args[1].isString()) + THROW_GENERIC_ERROR("qsTr(): second argument (disambiguation) must be a string"); + if ((callData->argc > 2) && !callData->args[2].isNumber()) + THROW_GENERIC_ERROR("qsTr(): third argument (n) must be a number"); + QString context; if (QQmlContextData *ctxt = scope.engine->callingQmlContext()) { QString path = ctxt->urlString(); @@ -1866,7 +1882,7 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx) int length = lastDot - (lastSlash + 1); context = (lastSlash > -1) ? path.mid(lastSlash + 1, (length > -1) ? length : -1) : QString(); } else { - ExecutionContext *parentCtx = scope.engine->parentContext(ctx); + ExecutionContext *parentCtx = scope.engine->currentContext; // The first non-empty source URL in the call stack determines the translation context. while (!!parentCtx && context.isEmpty()) { if (QV4::CompiledData::CompilationUnit *unit = parentCtx->d()->compilationUnit) { @@ -1885,18 +1901,18 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx) } } - QString text = ctx->args()[0].toQStringNoThrow(); + QString text = callData->args[0].toQStringNoThrow(); QString comment; - if (ctx->argc() > 1) - comment = ctx->args()[1].toQStringNoThrow(); + if (callData->argc > 1) + comment = callData->args[1].toQStringNoThrow(); int n = -1; - if (ctx->argc() > 2) - n = ctx->args()[2].toInt32(); + if (callData->argc > 2) + n = callData->args[2].toInt32(); QString result = QCoreApplication::translate(context.toUtf8().constData(), text.toUtf8().constData(), comment.toUtf8().constData(), n); - return ctx->d()->engine->newString(result)->asReturnedValue(); + scope.result = scope.engine->newString(result); } /*! @@ -1921,11 +1937,12 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx) \sa {Internationalization and Localization with Qt Quick} */ -ReturnedValue GlobalExtensions::method_qsTrNoOp(CallContext *ctx) +void GlobalExtensions::method_qsTrNoOp(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() < 1) - return QV4::Encode::undefined(); - return ctx->args()[0].asReturnedValue(); + if (callData->argc < 1) + scope.result = QV4::Encode::undefined(); + else + scope.result = callData->args[0]; } /*! @@ -1958,20 +1975,20 @@ ReturnedValue GlobalExtensions::method_qsTrNoOp(CallContext *ctx) \sa QT_TRID_NOOP(), {Internationalization and Localization with Qt Quick} */ -ReturnedValue GlobalExtensions::method_qsTrId(CallContext *ctx) +void GlobalExtensions::method_qsTrId(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() < 1) - V4THROW_ERROR("qsTrId() requires at least one argument"); - if (!ctx->args()[0].isString()) - V4THROW_TYPE("qsTrId(): first argument (id) must be a string"); - if (ctx->argc() > 1 && !ctx->args()[1].isNumber()) - V4THROW_TYPE("qsTrId(): second argument (n) must be a number"); + if (callData->argc < 1) + THROW_GENERIC_ERROR("qsTrId() requires at least one argument"); + if (!callData->args[0].isString()) + THROW_TYPE_ERROR_WITH_MESSAGE("qsTrId(): first argument (id) must be a string"); + if (callData->argc > 1 && !callData->args[1].isNumber()) + THROW_TYPE_ERROR_WITH_MESSAGE("qsTrId(): second argument (n) must be a number"); int n = -1; - if (ctx->argc() > 1) - n = ctx->args()[1].toInt32(); + if (callData->argc > 1) + n = callData->args[1].toInt32(); - return ctx->d()->engine->newString(qtTrId(ctx->args()[0].toQStringNoThrow().toUtf8().constData(), n))->asReturnedValue(); + scope.result = scope.engine->newString(qtTrId(callData->args[0].toQStringNoThrow().toUtf8().constData(), n)); } /*! @@ -1990,41 +2007,41 @@ ReturnedValue GlobalExtensions::method_qsTrId(CallContext *ctx) \sa qsTrId(), {Internationalization and Localization with Qt Quick} */ -ReturnedValue GlobalExtensions::method_qsTrIdNoOp(CallContext *ctx) +void GlobalExtensions::method_qsTrIdNoOp(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() < 1) - return QV4::Encode::undefined(); - return ctx->args()[0].asReturnedValue(); + if (callData->argc < 1) + scope.result = QV4::Encode::undefined(); + else + scope.result = callData->args[0]; } #endif // translation -QV4::ReturnedValue GlobalExtensions::method_gc(CallContext *ctx) +void GlobalExtensions::method_gc(const BuiltinFunction *, Scope &scope, CallData *) { - ctx->d()->engine->memoryManager->runGC(); + scope.engine->memoryManager->runGC(); - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } -ReturnedValue GlobalExtensions::method_string_arg(CallContext *ctx) +void GlobalExtensions::method_string_arg(const BuiltinFunction *, Scope &scope, CallData *callData) { - if (ctx->argc() != 1) - V4THROW_ERROR("String.arg(): Invalid arguments"); + if (callData->argc != 1) + THROW_GENERIC_ERROR("String.arg(): Invalid arguments"); - QString value = ctx->thisObject().toQString(); + QString value = callData->thisObject.toQString(); - QV4::Scope scope(ctx); - QV4::ScopedValue arg(scope, ctx->args()[0]); + QV4::ScopedValue arg(scope, callData->args[0]); if (arg->isInteger()) - return ctx->d()->engine->newString(value.arg(arg->integerValue()))->asReturnedValue(); + RETURN_RESULT(scope.engine->newString(value.arg(arg->integerValue()))); else if (arg->isDouble()) - return ctx->d()->engine->newString(value.arg(arg->doubleValue()))->asReturnedValue(); + RETURN_RESULT(scope.engine->newString(value.arg(arg->doubleValue()))); else if (arg->isBoolean()) - return ctx->d()->engine->newString(value.arg(arg->booleanValue()))->asReturnedValue(); + RETURN_RESULT(scope.engine->newString(value.arg(arg->booleanValue()))); - return ctx->d()->engine->newString(value.arg(arg->toQString()))->asReturnedValue(); + RETURN_RESULT(scope.engine->newString(value.arg(arg->toQString()))); } /*! @@ -2047,10 +2064,10 @@ be passed on to the function invoked. Note that if redundant calls are eliminated, then only the last set of arguments will be passed to the function. */ -ReturnedValue QtObject::method_callLater(CallContext *ctx) +void QtObject::method_callLater(const BuiltinFunction *b, Scope &scope, CallData *callData) { - QV8Engine *v8engine = ctx->engine()->v8Engine; - return v8engine->delayedCallQueue()->addUniquelyAndExecuteLater(ctx); + QV8Engine *v8engine = scope.engine->v8Engine; + v8engine->delayedCallQueue()->addUniquelyAndExecuteLater(b, scope, callData); } QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h index fe43532647..21613b7c10 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h +++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h @@ -93,45 +93,45 @@ struct QtObject : Object static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes); - static ReturnedValue method_isQtObject(CallContext *ctx); - static ReturnedValue method_rgba(CallContext *ctx); - static ReturnedValue method_hsla(CallContext *ctx); - static ReturnedValue method_hsva(CallContext *ctx); - static ReturnedValue method_colorEqual(CallContext *ctx); - static ReturnedValue method_font(CallContext *ctx); - static ReturnedValue method_rect(CallContext *ctx); - static ReturnedValue method_point(CallContext *ctx); - static ReturnedValue method_size(CallContext *ctx); - static ReturnedValue method_vector2d(CallContext *ctx); - static ReturnedValue method_vector3d(CallContext *ctx); - static ReturnedValue method_vector4d(CallContext *ctx); - static ReturnedValue method_quaternion(CallContext *ctx); - static ReturnedValue method_matrix4x4(CallContext *ctx); - static ReturnedValue method_lighter(CallContext *ctx); - static ReturnedValue method_darker(CallContext *ctx); - static ReturnedValue method_tint(CallContext *ctx); - static ReturnedValue method_formatDate(CallContext *ctx); - static ReturnedValue method_formatTime(CallContext *ctx); - static ReturnedValue method_formatDateTime(CallContext *ctx); - static ReturnedValue method_openUrlExternally(CallContext *ctx); - static ReturnedValue method_fontFamilies(CallContext *ctx); - static ReturnedValue method_md5(CallContext *ctx); - static ReturnedValue method_btoa(CallContext *ctx); - static ReturnedValue method_atob(CallContext *ctx); - static ReturnedValue method_quit(CallContext *ctx); - static ReturnedValue method_exit(CallContext *ctx); - static ReturnedValue method_resolvedUrl(CallContext *ctx); - static ReturnedValue method_createQmlObject(CallContext *ctx); - static ReturnedValue method_createComponent(CallContext *ctx); - static ReturnedValue method_locale(CallContext *ctx); - static ReturnedValue method_binding(CallContext *ctx); - - static ReturnedValue method_get_platform(CallContext *ctx); - static ReturnedValue method_get_application(CallContext *ctx); - static ReturnedValue method_get_inputMethod(CallContext *ctx); - static ReturnedValue method_get_styleHints(CallContext *ctx); - - static ReturnedValue method_callLater(CallContext *ctx); + static void method_isQtObject(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_rgba(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_hsla(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_hsva(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_colorEqual(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_font(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_rect(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_point(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_size(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_vector2d(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_vector3d(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_vector4d(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_quaternion(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_matrix4x4(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_lighter(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_darker(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_tint(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_formatDate(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_formatTime(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_formatDateTime(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_openUrlExternally(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_fontFamilies(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_md5(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_btoa(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_atob(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_quit(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_exit(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_resolvedUrl(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_createQmlObject(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_createComponent(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_locale(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_binding(const BuiltinFunction *, Scope &scope, CallData *callData); + + static void method_get_platform(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_get_application(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_get_inputMethod(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_get_styleHints(const BuiltinFunction *, Scope &scope, CallData *callData); + + static void method_callLater(const BuiltinFunction *, Scope &scope, CallData *callData); private: void addAll(); @@ -142,18 +142,18 @@ struct ConsoleObject : Object { V4_OBJECT2(ConsoleObject, Object) - static ReturnedValue method_error(CallContext *ctx); - static ReturnedValue method_log(CallContext *ctx); - static ReturnedValue method_info(CallContext *ctx); - static ReturnedValue method_profile(CallContext *ctx); - static ReturnedValue method_profileEnd(CallContext *ctx); - static ReturnedValue method_time(CallContext *ctx); - static ReturnedValue method_timeEnd(CallContext *ctx); - static ReturnedValue method_count(CallContext *ctx); - static ReturnedValue method_trace(CallContext *ctx); - static ReturnedValue method_warn(CallContext *ctx); - static ReturnedValue method_assert(CallContext *ctx); - static ReturnedValue method_exception(CallContext *ctx); + static void method_error(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_log(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_info(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_profile(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_profileEnd(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_time(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_timeEnd(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_count(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_trace(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_warn(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_assert(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_exception(const BuiltinFunction *, Scope &scope, CallData *callData); }; @@ -161,17 +161,17 @@ struct Q_QML_PRIVATE_EXPORT GlobalExtensions { static void init(Object *globalObject, QJSEngine::Extensions extensions); #if QT_CONFIG(translation) - static ReturnedValue method_qsTranslate(CallContext *ctx); - static ReturnedValue method_qsTranslateNoOp(CallContext *ctx); - static ReturnedValue method_qsTr(CallContext *ctx); - static ReturnedValue method_qsTrNoOp(CallContext *ctx); - static ReturnedValue method_qsTrId(CallContext *ctx); - static ReturnedValue method_qsTrIdNoOp(CallContext *ctx); + static void method_qsTranslate(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_qsTranslateNoOp(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_qsTr(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_qsTrNoOp(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_qsTrId(const BuiltinFunction *, Scope &scope, CallData *callData); + static void method_qsTrIdNoOp(const BuiltinFunction *, Scope &scope, CallData *callData); #endif - static ReturnedValue method_gc(CallContext *ctx); + static void method_gc(const BuiltinFunction *, Scope &scope, CallData *callData); // on String:prototype - static ReturnedValue method_string_arg(CallContext *ctx); + static void method_string_arg(const BuiltinFunction *, Scope &scope, CallData *callData); }; -- cgit v1.2.3 From 4d23faf34192cef372f846dcf02fd8cc398b14c0 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 6 Jan 2017 08:54:39 +0100 Subject: Port builtin methods in Canvas2D to new calling convention Change-Id: I0d141b3d655161a7892ffd0e5b8f019b3df51da9 Reviewed-by: Simon Hausmann --- src/qml/qml/v8/qv4domerrors_p.h | 7 - src/quick/items/context2d/qquickcontext2d.cpp | 1297 ++++++++++++------------- 2 files changed, 617 insertions(+), 687 deletions(-) diff --git a/src/qml/qml/v8/qv4domerrors_p.h b/src/qml/qml/v8/qv4domerrors_p.h index d2225ec591..a9bdbe01ae 100644 --- a/src/qml/qml/v8/qv4domerrors_p.h +++ b/src/qml/qml/v8/qv4domerrors_p.h @@ -74,13 +74,6 @@ QT_BEGIN_NAMESPACE #define DOMEXCEPTION_VALIDATION_ERR 16 #define DOMEXCEPTION_TYPE_MISMATCH_ERR 17 -#define V4THROW_DOM(error, string) { \ - QV4::ScopedValue v(scope, scope.engine->newString(QStringLiteral(string))); \ - QV4::ScopedObject ex(scope, scope.engine->newErrorObject(v)); \ - ex->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("code"))), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(error))); \ - return ctx->engine()->throwError(ex); \ -} - #define THROW_DOM(error, string) { \ QV4::ScopedValue v(scope, scope.engine->newString(QStringLiteral(string))); \ QV4::ScopedObject ex(scope, scope.engine->newErrorObject(v)); \ diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index bcaedd67b4..b0c1d50907 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -129,10 +129,10 @@ Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok); #define DEGREES(t) ((t) * 180.0 / M_PI) #define CHECK_CONTEXT(r) if (!r || !r->d()->context || !r->d()->context->bufferValid()) \ - V4THROW_ERROR("Not a Context2D object"); + THROW_GENERIC_ERROR("Not a Context2D object"); #define CHECK_CONTEXT_SETTER(r) if (!r || !r->d()->context || !r->d()->context->bufferValid()) \ - V4THROW_ERROR("Not a Context2D object"); + THROW_GENERIC_ERROR("Not a Context2D object"); #define qClamp(val, min, max) qMin(qMax(val, min), max) #define CHECK_RGBA(c) (c == '-' || c == '.' || (c >=0 && c <= 9)) QColor qt_color_from_string(const QV4::Value &name) @@ -537,45 +537,45 @@ struct QQuickJSContext2D : public QV4::Object { V4_OBJECT2(QQuickJSContext2D, QV4::Object) - static QV4::ReturnedValue method_get_globalAlpha(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_globalAlpha(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_globalCompositeOperation(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_globalCompositeOperation(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_fillStyle(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_fillStyle(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_fillRule(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_fillRule(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_strokeStyle(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_strokeStyle(QV4::CallContext *ctx); - - static QV4::ReturnedValue method_get_lineCap(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_lineCap(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_lineJoin(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_lineJoin(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_lineWidth(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_lineWidth(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_miterLimit(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_miterLimit(QV4::CallContext *ctx); - - static QV4::ReturnedValue method_get_shadowBlur(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_shadowBlur(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_shadowColor(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_shadowColor(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_shadowOffsetX(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_shadowOffsetX(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_shadowOffsetY(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_shadowOffsetY(QV4::CallContext *ctx); + static void method_get_globalAlpha(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_globalAlpha(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_globalCompositeOperation(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_globalCompositeOperation(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_fillStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_fillStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_fillRule(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_fillRule(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_strokeStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_strokeStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + + static void method_get_lineCap(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_lineCap(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_lineJoin(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_lineJoin(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_lineWidth(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_lineWidth(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_miterLimit(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_miterLimit(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + + static void method_get_shadowBlur(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_shadowBlur(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_shadowColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_shadowColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_shadowOffsetX(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_shadowOffsetX(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_shadowOffsetY(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_shadowOffsetY(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); // should these two be on the proto? - static QV4::ReturnedValue method_get_path(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_path(QV4::CallContext *ctx); - - static QV4::ReturnedValue method_get_font(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_font(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_textAlign(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_textAlign(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_textBaseline(QV4::CallContext *ctx); - static QV4::ReturnedValue method_set_textBaseline(QV4::CallContext *ctx); + static void method_get_path(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_path(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + + static void method_get_font(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_font(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_textAlign(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_textAlign(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_textBaseline(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_set_textBaseline(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); }; DEFINE_OBJECT_VTABLE(QQuickJSContext2D); @@ -638,50 +638,50 @@ public: return o->d(); } - static QV4::ReturnedValue method_get_canvas(QV4::CallContext *ctx); - static QV4::ReturnedValue method_restore(QV4::CallContext *ctx); - static QV4::ReturnedValue method_reset(QV4::CallContext *ctx); - static QV4::ReturnedValue method_save(QV4::CallContext *ctx); - static QV4::ReturnedValue method_rotate(QV4::CallContext *ctx); - static QV4::ReturnedValue method_scale(QV4::CallContext *ctx); - static QV4::ReturnedValue method_translate(QV4::CallContext *ctx); - static QV4::ReturnedValue method_setTransform(QV4::CallContext *ctx); - static QV4::ReturnedValue method_transform(QV4::CallContext *ctx); - static QV4::ReturnedValue method_resetTransform(QV4::CallContext *ctx); - static QV4::ReturnedValue method_shear(QV4::CallContext *ctx); - static QV4::ReturnedValue method_createLinearGradient(QV4::CallContext *ctx); - static QV4::ReturnedValue method_createRadialGradient(QV4::CallContext *ctx); - static QV4::ReturnedValue method_createConicalGradient(QV4::CallContext *ctx); - static QV4::ReturnedValue method_createPattern(QV4::CallContext *ctx); - static QV4::ReturnedValue method_clearRect(QV4::CallContext *ctx); - static QV4::ReturnedValue method_fillRect(QV4::CallContext *ctx); - static QV4::ReturnedValue method_strokeRect(QV4::CallContext *ctx); - static QV4::ReturnedValue method_arc(QV4::CallContext *ctx); - static QV4::ReturnedValue method_arcTo(QV4::CallContext *ctx); - static QV4::ReturnedValue method_beginPath(QV4::CallContext *ctx); - static QV4::ReturnedValue method_bezierCurveTo(QV4::CallContext *ctx); - static QV4::ReturnedValue method_clip(QV4::CallContext *ctx); - static QV4::ReturnedValue method_closePath(QV4::CallContext *ctx); - static QV4::ReturnedValue method_fill(QV4::CallContext *ctx); - static QV4::ReturnedValue method_lineTo(QV4::CallContext *ctx); - static QV4::ReturnedValue method_moveTo(QV4::CallContext *ctx); - static QV4::ReturnedValue method_quadraticCurveTo(QV4::CallContext *ctx); - static QV4::ReturnedValue method_rect(QV4::CallContext *ctx); - static QV4::ReturnedValue method_roundedRect(QV4::CallContext *ctx); - static QV4::ReturnedValue method_ellipse(QV4::CallContext *ctx); - static QV4::ReturnedValue method_text(QV4::CallContext *ctx); - static QV4::ReturnedValue method_stroke(QV4::CallContext *ctx); - static QV4::ReturnedValue method_isPointInPath(QV4::CallContext *ctx); - static QV4::ReturnedValue method_drawFocusRing(QV4::CallContext *ctx); - static QV4::ReturnedValue method_setCaretSelectionRect(QV4::CallContext *ctx); - static QV4::ReturnedValue method_caretBlinkRate(QV4::CallContext *ctx); - static QV4::ReturnedValue method_fillText(QV4::CallContext *ctx); - static QV4::ReturnedValue method_strokeText(QV4::CallContext *ctx); - static QV4::ReturnedValue method_measureText(QV4::CallContext *ctx); - static QV4::ReturnedValue method_drawImage(QV4::CallContext *ctx); - static QV4::ReturnedValue method_createImageData(QV4::CallContext *ctx); - static QV4::ReturnedValue method_getImageData(QV4::CallContext *ctx); - static QV4::ReturnedValue method_putImageData(QV4::CallContext *ctx); + static void method_get_canvas(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_restore(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_reset(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_save(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_rotate(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_scale(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_translate(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_setTransform(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_transform(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_resetTransform(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_shear(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_createLinearGradient(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_createRadialGradient(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_createConicalGradient(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_createPattern(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_clearRect(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_fillRect(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_strokeRect(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_arc(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_arcTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_beginPath(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_bezierCurveTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_clip(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_closePath(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_fill(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_lineTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_moveTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_quadraticCurveTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_rect(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_roundedRect(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_ellipse(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_text(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_stroke(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_isPointInPath(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_drawFocusRing(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_setCaretSelectionRect(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_caretBlinkRate(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_fillText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_strokeText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_measureText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_drawImage(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_createImageData(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_getImageData(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_putImageData(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); }; @@ -693,7 +693,7 @@ struct QQuickContext2DStyle : public QV4::Object V4_OBJECT2(QQuickContext2DStyle, QV4::Object) V4_NEEDS_DESTROY - static QV4::ReturnedValue gradient_proto_addColorStop(QV4::CallContext *ctx); + static void gradient_proto_addColorStop(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); }; @@ -903,7 +903,7 @@ struct QQuickJSContext2DPixelData : public QV4::Object static QV4::ReturnedValue getIndexed(const QV4::Managed *m, uint index, bool *hasProperty); static void putIndexed(QV4::Managed *m, uint index, const QV4::Value &value); - static QV4::ReturnedValue proto_get_length(QV4::CallContext *ctx); + static void proto_get_length(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); }; void QV4::Heap::QQuickJSContext2DPixelData::init() @@ -921,9 +921,9 @@ struct QQuickJSContext2DImageData : public QV4::Object { V4_OBJECT2(QQuickJSContext2DImageData, QV4::Object) - static QV4::ReturnedValue method_get_width(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_height(QV4::CallContext *ctx); - static QV4::ReturnedValue method_get_data(QV4::CallContext *ctx); + static void method_get_width(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_height(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); + static void method_get_data(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); static void markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *engine) { static_cast(that)->pixelData.mark(engine); @@ -975,13 +975,12 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionE This property is read only. */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_get_canvas(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_get_canvas(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) - return QV4::QObjectWrapper::wrap(scope.engine, r->d()->context->canvas()); + scope.result = QV4::QObjectWrapper::wrap(scope.engine, r->d()->context->canvas()); } /*! @@ -990,29 +989,27 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_get_canvas(QV4::CallContex \sa save() */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_restore(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_restore(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) r->d()->context->popState(); - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject.asReturnedValue(); } /*! \qmlmethod object QtQuick::Context2D::reset() Resets the context state and properties to the default values. */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_reset(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_reset(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) r->d()->context->reset(); - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject.asReturnedValue(); } /*! @@ -1045,15 +1042,14 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_reset(QV4::CallContext *ct The current path is NOT part of the drawing state. The path can be reset by invoking the beginPath() method. */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_save(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_save(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) r->d()->context->pushState(); - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject; } // transformations @@ -1074,15 +1070,14 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_save(QV4::CallContext *ctx where the \a angle of rotation is in radians. */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_rotate(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_rotate(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) - if (ctx->argc() >= 1) - r->d()->context->rotate(ctx->args()[0].toNumber()); - return ctx->thisObject().asReturnedValue(); + if (callData->argc >= 1) + r->d()->context->rotate(callData->args[0].toNumber()); + scope.result = callData->thisObject; } /*! @@ -1102,16 +1097,16 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_rotate(QV4::CallContext *c \image qml-item-canvas-scale.png */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_scale(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_scale(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) - if (ctx->argc() >= 2) - r->d()->context->scale(ctx->args()[0].toNumber(), ctx->args()[1].toNumber()); - return ctx->thisObject().asReturnedValue(); + if (callData->argc >= 2) + r->d()->context->scale(callData->args[0].toNumber(), callData->args[1].toNumber()); + scope.result = callData->thisObject; + } /*! @@ -1148,22 +1143,22 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_scale(QV4::CallContext *ct \sa transform() */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_setTransform(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_setTransform(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) - if (ctx->argc() >= 6) - r->d()->context->setTransform( ctx->args()[0].toNumber() - , ctx->args()[1].toNumber() - , ctx->args()[2].toNumber() - , ctx->args()[3].toNumber() - , ctx->args()[4].toNumber() - , ctx->args()[5].toNumber()); + if (callData->argc >= 6) + r->d()->context->setTransform( callData->args[0].toNumber() + , callData->args[1].toNumber() + , callData->args[2].toNumber() + , callData->args[3].toNumber() + , callData->args[4].toNumber() + , callData->args[5].toNumber()); + + scope.result = callData->thisObject; - return ctx->thisObject().asReturnedValue(); } /*! @@ -1177,21 +1172,21 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_setTransform(QV4::CallCont \sa setTransform() */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_transform(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_transform(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) - if (ctx->argc() >= 6) - r->d()->context->transform( ctx->args()[0].toNumber() - , ctx->args()[1].toNumber() - , ctx->args()[2].toNumber() - , ctx->args()[3].toNumber() - , ctx->args()[4].toNumber() - , ctx->args()[5].toNumber()); + if (callData->argc >= 6) + r->d()->context->transform( callData->args[0].toNumber() + , callData->args[1].toNumber() + , callData->args[2].toNumber() + , callData->args[3].toNumber() + , callData->args[4].toNumber() + , callData->args[5].toNumber()); + + scope.result = callData->thisObject; - return ctx->thisObject().asReturnedValue(); } /*! @@ -1203,15 +1198,15 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_transform(QV4::CallContext Translating the origin enables you to draw patterns of different objects on the canvas without having to measure the coordinates manually for each shape. */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_translate(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_translate(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) - if (ctx->argc() >= 2) - r->d()->context->translate(ctx->args()[0].toNumber(), ctx->args()[1].toNumber()); - return ctx->thisObject().asReturnedValue(); + if (callData->argc >= 2) + r->d()->context->translate(callData->args[0].toNumber(), callData->args[1].toNumber()); + scope.result = callData->thisObject; + } @@ -1223,15 +1218,15 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_translate(QV4::CallContext \sa transform(), setTransform(), reset() */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_resetTransform(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_resetTransform(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) r->d()->context->setTransform(1, 0, 0, 1, 0, 0); - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject; + } @@ -1241,16 +1236,16 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_resetTransform(QV4::CallCo Shears the transformation matrix by \a sh in the horizontal direction and \a sv in the vertical direction. */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_shear(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_shear(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) - if (ctx->argc() >= 2) - r->d()->context->shear(ctx->args()[0].toNumber(), ctx->args()[1].toNumber()); + if (callData->argc >= 2) + r->d()->context->shear(callData->args[0].toNumber(), callData->args[1].toNumber()); + + scope.result = callData->thisObject; - return ctx->thisObject().asReturnedValue(); } // compositing @@ -1261,31 +1256,30 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_shear(QV4::CallContext *ct The value must be in the range from \c 0.0 (fully transparent) to \c 1.0 (fully opaque). The default value is \c 1.0. */ -QV4::ReturnedValue QQuickJSContext2D::method_get_globalAlpha(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_globalAlpha(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) - return QV4::Encode(r->d()->context->state.globalAlpha); + scope.result = QV4::Encode(r->d()->context->state.globalAlpha); } -QV4::ReturnedValue QQuickJSContext2D::method_set_globalAlpha(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_globalAlpha(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT_SETTER(r) - double globalAlpha = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); + double globalAlpha = callData->argc ? callData->args[0].toNumber() : qt_qnan(); + + scope.result = QV4::Encode::undefined(); if (!qt_is_finite(globalAlpha)) - return QV4::Encode::undefined(); + return; if (globalAlpha >= 0.0 && globalAlpha <= 1.0 && r->d()->context->state.globalAlpha != globalAlpha) { r->d()->context->state.globalAlpha = globalAlpha; r->d()->context->buffer()->setGlobalAlpha(r->d()->context->state.globalAlpha); } - return QV4::Encode::undefined(); } /*! @@ -1314,34 +1308,33 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_globalAlpha(QV4::CallContext *c extension composition modes are provided as "vendorName-operationName" syntax, for example: QPainter::CompositionMode_Exclusion is provided as "qt-exclusion". */ -QV4::ReturnedValue QQuickJSContext2D::method_get_globalCompositeOperation(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_globalCompositeOperation(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) - return QV4::Encode(scope.engine->newString(qt_composite_mode_to_string(r->d()->context->state.globalCompositeOperation))); + scope.result = scope.engine->newString(qt_composite_mode_to_string(r->d()->context->state.globalCompositeOperation)); } -QV4::ReturnedValue QQuickJSContext2D::method_set_globalCompositeOperation(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_globalCompositeOperation(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT_SETTER(r) - if (!ctx->argc()) - return ctx->engine()->throwTypeError(); + if (!callData->argc) + THROW_TYPE_ERROR(); - QString mode = ctx->args()[0].toQString(); + scope.result = QV4::Encode::undefined(); + + QString mode = callData->args[0].toQString(); QPainter::CompositionMode cm = qt_composite_mode_from_string(mode); if (cm == QPainter::CompositionMode_SourceOver && mode != QLatin1String("source-over")) - return QV4::Encode::undefined(); + return; if (cm != r->d()->context->state.globalCompositeOperation) { r->d()->context->state.globalCompositeOperation = cm; r->d()->context->buffer()->setGlobalCompositeOperation(cm); } - return QV4::Encode::undefined(); } // colors and styles @@ -1367,34 +1360,32 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_globalCompositeOperation(QV4::C \sa createPattern() \sa strokeStyle */ -QV4::ReturnedValue QQuickJSContext2D::method_get_fillStyle(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_fillStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) QColor color = r->d()->context->state.fillStyle.color(); if (color.isValid()) { if (color.alpha() == 255) - return QV4::Encode(scope.engine->newString(color.name())); + RETURN_RESULT(scope.engine->newString(color.name())); QString alphaString = QString::number(color.alphaF(), 'f'); while (alphaString.endsWith(QLatin1Char('0'))) alphaString.chop(1); if (alphaString.endsWith(QLatin1Char('.'))) alphaString += QLatin1Char('0'); QString str = QString::fromLatin1("rgba(%1, %2, %3, %4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(alphaString); - return QV4::Encode(scope.engine->newString(str)); + RETURN_RESULT(scope.engine->newString(str)); } - return r->d()->context->m_fillStyle.value(); + scope.result = r->d()->context->m_fillStyle.value(); } -QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_fillStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT_SETTER(r) - QV4::ScopedValue value(scope, ctx->argument(0)); + QV4::ScopedValue value(scope, callData->argument(0)); if (value->as()) { QColor color = scope.engine->toVariant(value, qMetaTypeId()).value(); @@ -1420,7 +1411,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::CallContext *ctx r->d()->context->m_fillStyle.set(scope.engine, value); } } - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } /*! \qmlproperty enumeration QtQuick::Context2D::fillRule @@ -1434,22 +1425,20 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::CallContext *ctx \sa fillStyle */ -QV4::ReturnedValue QQuickJSContext2D::method_get_fillRule(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_fillRule(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) - return scope.engine->fromVariant(r->d()->context->state.fillRule); + scope.result = scope.engine->fromVariant(r->d()->context->state.fillRule); } -QV4::ReturnedValue QQuickJSContext2D::method_set_fillRule(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_fillRule(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT_SETTER(r) - QV4::ScopedValue value(scope, ctx->argument(0)); + QV4::ScopedValue value(scope, callData->argument(0)); if ((value->isString() && value->toQString() == QLatin1String("WindingFill")) || (value->isInt32() && value->integerValue() == Qt::WindingFill)) { @@ -1461,7 +1450,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillRule(QV4::CallContext *ctx) //error } r->d()->context->m_path.setFillRule(r->d()->context->state.fillRule); - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } /*! \qmlproperty variant QtQuick::Context2D::strokeStyle @@ -1476,34 +1465,32 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillRule(QV4::CallContext *ctx) \sa createPattern() \sa fillStyle */ -QV4::ReturnedValue QQuickJSContext2D::method_get_strokeStyle(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_strokeStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) QColor color = r->d()->context->state.strokeStyle.color(); if (color.isValid()) { if (color.alpha() == 255) - return QV4::Encode(scope.engine->newString(color.name())); + RETURN_RESULT(scope.engine->newString(color.name())); QString alphaString = QString::number(color.alphaF(), 'f'); while (alphaString.endsWith(QLatin1Char('0'))) alphaString.chop(1); if (alphaString.endsWith(QLatin1Char('.'))) alphaString += QLatin1Char('0'); QString str = QString::fromLatin1("rgba(%1, %2, %3, %4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(alphaString); - return QV4::Encode(scope.engine->newString(str)); + RETURN_RESULT(scope.engine->newString(str)); } - return r->d()->context->m_strokeStyle.value(); + scope.result = r->d()->context->m_strokeStyle.value(); } -QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_strokeStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT_SETTER(r) - QV4::ScopedValue value(scope, ctx->argument(0)); + QV4::ScopedValue value(scope, callData->argument(0)); if (value->as()) { QColor color = scope.engine->toVariant(value, qMetaTypeId()).value(); @@ -1530,7 +1517,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::CallContext *c r->d()->context->m_strokeStyle.set(scope.engine, value); } } - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } /*! @@ -1550,23 +1537,22 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::CallContext *c \sa strokeStyle */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_createLinearGradient(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) - if (ctx->argc() >= 4) { - qreal x0 = ctx->args()[0].toNumber(); - qreal y0 = ctx->args()[1].toNumber(); - qreal x1 = ctx->args()[2].toNumber(); - qreal y1 = ctx->args()[3].toNumber(); + if (callData->argc >= 4) { + qreal x0 = callData->args[0].toNumber(); + qreal y0 = callData->args[1].toNumber(); + qreal x1 = callData->args[2].toNumber(); + qreal y1 = callData->args[3].toNumber(); if (!qt_is_finite(x0) || !qt_is_finite(y0) || !qt_is_finite(x1) || !qt_is_finite(y1)) { - V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createLinearGradient(): Incorrect arguments") + THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createLinearGradient(): Incorrect arguments") } QQuickContext2DEngineData *ed = engineData(scope.engine); @@ -1574,10 +1560,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4:: QV4::ScopedObject p(scope, ed->gradientProto.value()); gradient->setPrototype(p); *gradient->d()->brush = QLinearGradient(x0, y0, x1, y1); - return gradient.asReturnedValue(); + RETURN_RESULT(gradient); } - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject; + } /*! @@ -1593,19 +1580,18 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4:: \sa strokeStyle */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_createRadialGradient(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) - if (ctx->argc() >= 6) { - qreal x0 = ctx->args()[0].toNumber(); - qreal y0 = ctx->args()[1].toNumber(); - qreal r0 = ctx->args()[2].toNumber(); - qreal x1 = ctx->args()[3].toNumber(); - qreal y1 = ctx->args()[4].toNumber(); - qreal r1 = ctx->args()[5].toNumber(); + if (callData->argc >= 6) { + qreal x0 = callData->args[0].toNumber(); + qreal y0 = callData->args[1].toNumber(); + qreal r0 = callData->args[2].toNumber(); + qreal x1 = callData->args[3].toNumber(); + qreal y1 = callData->args[4].toNumber(); + qreal r1 = callData->args[5].toNumber(); if (!qt_is_finite(x0) || !qt_is_finite(y0) @@ -1613,11 +1599,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4:: || !qt_is_finite(r0) || !qt_is_finite(r1) || !qt_is_finite(y1)) { - V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createRadialGradient(): Incorrect arguments") + THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createRadialGradient(): Incorrect arguments") } if (r0 < 0 || r1 < 0) - V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createRadialGradient(): Incorrect arguments") + THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createRadialGradient(): Incorrect arguments") QQuickContext2DEngineData *ed = engineData(scope.engine); @@ -1625,10 +1611,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4:: QV4::ScopedObject p(scope, ed->gradientProto.value()); gradient->setPrototype(p); *gradient->d()->brush = QRadialGradient(QPointF(x1, y1), r0+r1, QPointF(x0, y0)); - return gradient.asReturnedValue(); + RETURN_RESULT(gradient); } - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject; + } /*! @@ -1644,22 +1631,21 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4:: \sa strokeStyle */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_createConicalGradient(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) - if (ctx->argc() >= 3) { - qreal x = ctx->args()[0].toNumber(); - qreal y = ctx->args()[1].toNumber(); - qreal angle = DEGREES(ctx->args()[2].toNumber()); + if (callData->argc >= 3) { + qreal x = callData->args[0].toNumber(); + qreal y = callData->args[1].toNumber(); + qreal angle = DEGREES(callData->args[2].toNumber()); if (!qt_is_finite(x) || !qt_is_finite(y)) { - V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createConicalGradient(): Incorrect arguments"); + THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createConicalGradient(): Incorrect arguments"); } if (!qt_is_finite(angle)) { - V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createConicalGradient(): Incorrect arguments"); + THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createConicalGradient(): Incorrect arguments"); } QQuickContext2DEngineData *ed = engineData(scope.engine); @@ -1668,10 +1654,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4: QV4::ScopedObject p(scope, ed->gradientProto.value()); gradient->setPrototype(p); *gradient->d()->brush = QConicalGradient(x, y, angle); - return gradient.asReturnedValue(); + RETURN_RESULT(gradient); } - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject; + } /*! \qmlmethod variant QtQuick::Context2D::createPattern(color color, enumeration patternMode) @@ -1716,18 +1703,17 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4: \sa strokeStyle \sa fillStyle */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_createPattern(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - if (ctx->argc() >= 2) { + if (callData->argc >= 2) { QV4::Scoped pattern(scope, scope.engine->memoryManager->allocObject()); - QColor color = scope.engine->toVariant(ctx->args()[0], qMetaTypeId()).value(); + QColor color = scope.engine->toVariant(callData->args[0], qMetaTypeId()).value(); if (color.isValid()) { - int patternMode = ctx->args()[1].toInt32(); + int patternMode = callData->args[1].toInt32(); Qt::BrushStyle style = Qt::SolidPattern; if (patternMode >= 0 && patternMode < Qt::LinearGradientPattern) { style = static_cast(patternMode); @@ -1736,20 +1722,20 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallCon } else { QImage patternTexture; - if (const QV4::Object *o = ctx->args()[0].as()) { + if (const QV4::Object *o = callData->args[0].as()) { QV4::ScopedString s(scope, scope.engine->newString(QStringLiteral("data"))); QV4::Scoped pixelData(scope, o->get(s)); if (!!pixelData) { patternTexture = *pixelData->d()->image; } } else { - patternTexture = r->d()->context->createPixmap(QUrl(ctx->args()[0].toQStringNoThrow()))->image(); + patternTexture = r->d()->context->createPixmap(QUrl(callData->args[0].toQStringNoThrow()))->image(); } if (!patternTexture.isNull()) { pattern->d()->brush->setTextureImage(patternTexture); - QString repetition = ctx->args()[1].toQStringNoThrow(); + QString repetition = callData->args[1].toQStringNoThrow(); if (repetition == QLatin1String("repeat") || repetition.isEmpty()) { pattern->d()->patternRepeatX = true; pattern->d()->patternRepeatY = true; @@ -1769,10 +1755,10 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallCon } } - return pattern.asReturnedValue(); + RETURN_RESULT(pattern); } - return QV4::Encode::undefined(); + scope.result = QV4::Encode::undefined(); } // line styles @@ -1787,31 +1773,29 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallCon \endlist Other values are ignored. */ -QV4::ReturnedValue QQuickJSContext2D::method_get_lineCap(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_lineCap(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) switch (r->d()->context->state.lineCap) { case Qt::RoundCap: - return QV4::Encode(scope.engine->newString(QStringLiteral("round"))); + RETURN_RESULT(scope.engine->newString(QStringLiteral("round"))); case Qt::SquareCap: - return QV4::Encode(scope.engine->newString(QStringLiteral("square"))); + RETURN_RESULT(scope.engine->newString(QStringLiteral("square"))); case Qt::FlatCap: default: break; } - return QV4::Encode(scope.engine->newString(QStringLiteral("butt"))); + RETURN_RESULT(scope.engine->newString(QStringLiteral("butt"))); } -QV4::ReturnedValue QQuickJSContext2D::method_set_lineCap(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_lineCap(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT_SETTER(r) - QString lineCap = ctx->args()[0].toQString(); + QString lineCap = callData->args[0].toQString(); Qt::PenCapStyle cap; if (lineCap == QLatin1String("round")) cap = Qt::RoundCap; @@ -1820,13 +1804,13 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineCap(QV4::CallContext *ctx) else if (lineCap == QLatin1String("square")) cap = Qt::SquareCap; else - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); if (cap != r->d()->context->state.lineCap) { r->d()->context->state.lineCap = cap; r->d()->context->buffer()->setLineCap(cap); } - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } /*! @@ -1843,34 +1827,32 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineCap(QV4::CallContext *ctx) \endlist Other values are ignored. */ -QV4::ReturnedValue QQuickJSContext2D::method_get_lineJoin(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_lineJoin(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) switch (r->d()->context->state.lineJoin) { case Qt::RoundJoin: - return QV4::Encode(scope.engine->newString(QStringLiteral("round"))); + RETURN_RESULT(scope.engine->newString(QStringLiteral("round"))); case Qt::BevelJoin: - return QV4::Encode(scope.engine->newString(QStringLiteral("bevel"))); + RETURN_RESULT(scope.engine->newString(QStringLiteral("bevel"))); case Qt::MiterJoin: default: break; } - return QV4::Encode(scope.engine->newString(QStringLiteral("miter"))); + RETURN_RESULT(scope.engine->newString(QStringLiteral("miter"))); } -QV4::ReturnedValue QQuickJSContext2D::method_set_lineJoin(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_lineJoin(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT_SETTER(r) - if (!ctx->argc()) - return ctx->engine()->throwTypeError(); + if (!callData->argc) + THROW_TYPE_ERROR(); - QString lineJoin = ctx->args()[0].toQString(); + QString lineJoin = callData->args[0].toQString(); Qt::PenJoinStyle join; if (lineJoin == QLatin1String("round")) join = Qt::RoundJoin; @@ -1879,41 +1861,39 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineJoin(QV4::CallContext *ctx) else if (lineJoin == QLatin1String("miter")) join = Qt::SvgMiterJoin; else - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); if (join != r->d()->context->state.lineJoin) { r->d()->context->state.lineJoin = join; r->d()->context->buffer()->setLineJoin(join); } - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } /*! \qmlproperty real QtQuick::Context2D::lineWidth Holds the current line width. Values that are not finite values greater than zero are ignored. */ -QV4::ReturnedValue QQuickJSContext2D::method_get_lineWidth(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_lineWidth(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - return QV4::Encode(r->d()->context->state.lineWidth); + RETURN_RESULT(r->d()->context->state.lineWidth); } -QV4::ReturnedValue QQuickJSContext2D::method_set_lineWidth(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_lineWidth(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT_SETTER(r) - qreal w = ctx->argc() ? ctx->args()[0].toNumber() : -1; + qreal w = callData->argc ? callData->args[0].toNumber() : -1; if (w > 0 && qt_is_finite(w) && w != r->d()->context->state.lineWidth) { r->d()->context->state.lineWidth = w; r->d()->context->buffer()->setLineWidth(w); } - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } /*! @@ -1921,28 +1901,26 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineWidth(QV4::CallContext *ctx Holds the current miter limit ratio. The default miter limit value is 10.0. */ -QV4::ReturnedValue QQuickJSContext2D::method_get_miterLimit(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_miterLimit(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - return QV4::Encode(r->d()->context->state.miterLimit); + RETURN_RESULT(r->d()->context->state.miterLimit); } -QV4::ReturnedValue QQuickJSContext2D::method_set_miterLimit(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_miterLimit(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT_SETTER(r) - qreal ml = ctx->argc() ? ctx->args()[0].toNumber() : -1; + qreal ml = callData->argc ? callData->args[0].toNumber() : -1; if (ml > 0 && qt_is_finite(ml) && ml != r->d()->context->state.miterLimit) { r->d()->context->state.miterLimit = ml; r->d()->context->buffer()->setMiterLimit(ml); } - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } // shadows @@ -1950,58 +1928,54 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_miterLimit(QV4::CallContext *ct \qmlproperty real QtQuick::Context2D::shadowBlur Holds the current level of blur applied to shadows */ -QV4::ReturnedValue QQuickJSContext2D::method_get_shadowBlur(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_shadowBlur(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - return QV4::Encode(r->d()->context->state.shadowBlur); + RETURN_RESULT(r->d()->context->state.shadowBlur); } -QV4::ReturnedValue QQuickJSContext2D::method_set_shadowBlur(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_shadowBlur(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT_SETTER(r) - qreal blur = ctx->argc() ? ctx->args()[0].toNumber() : -1; + qreal blur = callData->argc ? callData->args[0].toNumber() : -1; if (blur > 0 && qt_is_finite(blur) && blur != r->d()->context->state.shadowBlur) { r->d()->context->state.shadowBlur = blur; r->d()->context->buffer()->setShadowBlur(blur); } - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } /*! \qmlproperty string QtQuick::Context2D::shadowColor Holds the current shadow color. */ -QV4::ReturnedValue QQuickJSContext2D::method_get_shadowColor(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_shadowColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - return QV4::Encode(scope.engine->newString(r->d()->context->state.shadowColor.name())); + RETURN_RESULT(scope.engine->newString(r->d()->context->state.shadowColor.name())); } -QV4::ReturnedValue QQuickJSContext2D::method_set_shadowColor(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_shadowColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT_SETTER(r) QColor color; - if (ctx->argc()) - color = qt_color_from_string(ctx->args()[0]); + if (callData->argc) + color = qt_color_from_string(callData->args[0]); if (color.isValid() && color != r->d()->context->state.shadowColor) { r->d()->context->state.shadowColor = color; r->d()->context->buffer()->setShadowColor(color); } - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } @@ -2011,27 +1985,25 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowColor(QV4::CallContext *c \sa shadowOffsetY */ -QV4::ReturnedValue QQuickJSContext2D::method_get_shadowOffsetX(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_shadowOffsetX(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - return QV4::Encode(r->d()->context->state.shadowOffsetX); + RETURN_RESULT(r->d()->context->state.shadowOffsetX); } -QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetX(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_shadowOffsetX(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT_SETTER(r) - qreal offsetX = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); + qreal offsetX = callData->argc ? callData->args[0].toNumber() : qt_qnan(); if (qt_is_finite(offsetX) && offsetX != r->d()->context->state.shadowOffsetX) { r->d()->context->state.shadowOffsetX = offsetX; r->d()->context->buffer()->setShadowOffsetX(offsetX); } - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } /*! \qmlproperty qreal QtQuick::Context2D::shadowOffsetY @@ -2039,45 +2011,41 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetX(QV4::CallContext \sa shadowOffsetX */ -QV4::ReturnedValue QQuickJSContext2D::method_get_shadowOffsetY(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_shadowOffsetY(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - return QV4::Encode(r->d()->context->state.shadowOffsetY); + RETURN_RESULT(r->d()->context->state.shadowOffsetY); } -QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetY(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_shadowOffsetY(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT_SETTER(r) - qreal offsetY = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan(); + qreal offsetY = callData->argc ? callData->args[0].toNumber() : qt_qnan(); if (qt_is_finite(offsetY) && offsetY != r->d()->context->state.shadowOffsetY) { r->d()->context->state.shadowOffsetY = offsetY; r->d()->context->buffer()->setShadowOffsetY(offsetY); } - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } -QV4::ReturnedValue QQuickJSContext2D::method_get_path(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_path(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - return r->d()->context->m_v4path.value(); + scope.result = r->d()->context->m_v4path.value(); } -QV4::ReturnedValue QQuickJSContext2D::method_set_path(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_path(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT_SETTER(r) - QV4::ScopedValue value(scope, ctx->argument(0)); + QV4::ScopedValue value(scope, callData->argument(0)); r->d()->context->beginPath(); QV4::Scoped qobjectWrapper(scope, value); if (!!qobjectWrapper) { @@ -2088,7 +2056,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_path(QV4::CallContext *ctx) QQuickSvgParser::parsePathDataFast(path, r->d()->context->m_path); } r->d()->context->m_v4path.set(scope.engine, value); - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } //rects @@ -2096,20 +2064,20 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_path(QV4::CallContext *ctx) \qmlmethod object QtQuick::Context2D::clearRect(real x, real y, real w, real h) Clears all pixels on the canvas in the given rectangle to transparent black. */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_clearRect(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_clearRect(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - if (ctx->argc() >= 4) - r->d()->context->clearRect(ctx->args()[0].toNumber(), - ctx->args()[1].toNumber(), - ctx->args()[2].toNumber(), - ctx->args()[3].toNumber()); + if (callData->argc >= 4) + r->d()->context->clearRect(callData->args[0].toNumber(), + callData->args[1].toNumber(), + callData->args[2].toNumber(), + callData->args[3].toNumber()); + + scope.result = callData->thisObject; - return ctx->thisObject().asReturnedValue(); } /*! \qmlmethod object QtQuick::Context2D::fillRect(real x, real y, real w, real h) @@ -2117,15 +2085,15 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_clearRect(QV4::CallContext \sa fillStyle */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillRect(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_fillRect(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - if (ctx->argc() >= 4) - r->d()->context->fillRect(ctx->args()[0].toNumber(), ctx->args()[1].toNumber(), ctx->args()[2].toNumber(), ctx->args()[3].toNumber()); - return ctx->thisObject().asReturnedValue(); + if (callData->argc >= 4) + r->d()->context->fillRect(callData->args[0].toNumber(), callData->args[1].toNumber(), callData->args[2].toNumber(), callData->args[3].toNumber()); + scope.result = callData->thisObject; + } /*! @@ -2138,16 +2106,16 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillRect(QV4::CallContext \sa lineJoin \sa miterLimit */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeRect(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_strokeRect(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - if (ctx->argc() >= 4) - r->d()->context->strokeRect(ctx->args()[0].toNumber(), ctx->args()[1].toNumber(), ctx->args()[2].toNumber(), ctx->args()[3].toNumber()); + if (callData->argc >= 4) + r->d()->context->strokeRect(callData->args[0].toNumber(), callData->args[1].toNumber(), callData->args[2].toNumber(), callData->args[3].toNumber()); + + scope.result = callData->thisObject; - return ctx->thisObject().asReturnedValue(); } // Complex shapes (paths) API @@ -2171,32 +2139,32 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeRect(QV4::CallContex \sa arcTo, {http://www.w3.org/TR/2dcontext/#dom-context-2d-arc}{W3C's 2D Context Standard for arc()} */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_arc(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_arc(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - if (ctx->argc() >= 5) { + if (callData->argc >= 5) { bool antiClockwise = false; - if (ctx->argc() == 6) - antiClockwise = ctx->args()[5].toBoolean(); + if (callData->argc == 6) + antiClockwise = callData->args[5].toBoolean(); - qreal radius = ctx->args()[2].toNumber(); + qreal radius = callData->args[2].toNumber(); if (qt_is_finite(radius) && radius < 0) - V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius"); + THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius"); - r->d()->context->arc(ctx->args()[0].toNumber(), - ctx->args()[1].toNumber(), + r->d()->context->arc(callData->args[0].toNumber(), + callData->args[1].toNumber(), radius, - ctx->args()[3].toNumber(), - ctx->args()[4].toNumber(), + callData->args[3].toNumber(), + callData->args[4].toNumber(), antiClockwise); } - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject; + } /*! @@ -2222,26 +2190,26 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_arc(QV4::CallContext *ctx) \sa arc, {http://www.w3.org/TR/2dcontext/#dom-context-2d-arcto}{W3C's 2D Context Standard for arcTo()} */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_arcTo(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_arcTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - if (ctx->argc() >= 5) { - qreal radius = ctx->args()[4].toNumber(); + if (callData->argc >= 5) { + qreal radius = callData->args[4].toNumber(); if (qt_is_finite(radius) && radius < 0) - V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius"); + THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius"); - r->d()->context->arcTo(ctx->args()[0].toNumber(), - ctx->args()[1].toNumber(), - ctx->args()[2].toNumber(), - ctx->args()[3].toNumber(), + r->d()->context->arcTo(callData->args[0].toNumber(), + callData->args[1].toNumber(), + callData->args[2].toNumber(), + callData->args[3].toNumber(), radius); } - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject; + } /*! @@ -2249,15 +2217,15 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_arcTo(QV4::CallContext *ct Resets the current path to a new path. */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_beginPath(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_beginPath(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) r->d()->context->beginPath(); - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject; + } /*! @@ -2279,28 +2247,26 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_beginPath(QV4::CallContext \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-beziercurveto}{W3C 2d context standard for bezierCurveTo} \sa {http://www.openrise.com/lab/FlowerPower/}{The beautiful flower demo by using bezierCurveTo} */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_bezierCurveTo(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_bezierCurveTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) + scope.result = callData->thisObject; - if (ctx->argc() >= 6) { - qreal cp1x = ctx->args()[0].toNumber(); - qreal cp1y = ctx->args()[1].toNumber(); - qreal cp2x = ctx->args()[2].toNumber(); - qreal cp2y = ctx->args()[3].toNumber(); - qreal x = ctx->args()[4].toNumber(); - qreal y = ctx->args()[5].toNumber(); + if (callData->argc >= 6) { + qreal cp1x = callData->args[0].toNumber(); + qreal cp1y = callData->args[1].toNumber(); + qreal cp2x = callData->args[2].toNumber(); + qreal cp2y = callData->args[3].toNumber(); + qreal x = callData->args[4].toNumber(); + qreal y = callData->args[5].toNumber(); if (!qt_is_finite(cp1x) || !qt_is_finite(cp1y) || !qt_is_finite(cp2x) || !qt_is_finite(cp2y) || !qt_is_finite(x) || !qt_is_finite(y)) - return ctx->thisObject().asReturnedValue(); + return; r->d()->context->bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); } - - return ctx->thisObject().asReturnedValue(); } /*! @@ -2327,14 +2293,13 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_bezierCurveTo(QV4::CallCon \sa fill() \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-clip}{W3C 2d context standard for clip} */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_clip(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_clip(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) r->d()->context->clip(); - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject; } /*! @@ -2344,16 +2309,15 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_clip(QV4::CallContext *ctx \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-closepath}{W3C 2d context standard for closePath} */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_closePath(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_closePath(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) r->d()->context->closePath(); - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject; } /*! @@ -2365,13 +2329,12 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_closePath(QV4::CallContext \sa fillStyle */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_fill(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_fill(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r); r->d()->context->fill(); - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject; } /*! @@ -2379,24 +2342,22 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_fill(QV4::CallContext *ctx Draws a line from the current position to the point (x, y). */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_lineTo(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_lineTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) + scope.result = callData->thisObject; - if (ctx->argc() >= 2) { - qreal x = ctx->args()[0].toNumber(); - qreal y = ctx->args()[1].toNumber(); + if (callData->argc >= 2) { + qreal x = callData->args[0].toNumber(); + qreal y = callData->args[1].toNumber(); if (!qt_is_finite(x) || !qt_is_finite(y)) - return ctx->thisObject().asReturnedValue(); + return; r->d()->context->lineTo(x, y); } - - return ctx->thisObject().asReturnedValue(); } /*! @@ -2404,21 +2365,21 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_lineTo(QV4::CallContext *c Creates a new subpath with the given point. */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_moveTo(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_moveTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - if (ctx->argc() >= 2) { - qreal x = ctx->args()[0].toNumber(); - qreal y = ctx->args()[1].toNumber(); + scope.result = callData->thisObject; + + if (callData->argc >= 2) { + qreal x = callData->args[0].toNumber(); + qreal y = callData->args[1].toNumber(); if (!qt_is_finite(x) || !qt_is_finite(y)) - return ctx->thisObject().asReturnedValue(); + return; r->d()->context->moveTo(x, y); } - return ctx->thisObject().asReturnedValue(); } /*! @@ -2428,25 +2389,24 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_moveTo(QV4::CallContext *c See \l{http://www.w3.org/TR/2dcontext/#dom-context-2d-quadraticcurveto}{W3C 2d context standard for quadraticCurveTo} */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_quadraticCurveTo(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_quadraticCurveTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - if (ctx->argc() >= 4) { - qreal cpx = ctx->args()[0].toNumber(); - qreal cpy = ctx->args()[1].toNumber(); - qreal x = ctx->args()[2].toNumber(); - qreal y = ctx->args()[3].toNumber(); + scope.result = callData->thisObject; + + if (callData->argc >= 4) { + qreal cpx = callData->args[0].toNumber(); + qreal cpy = callData->args[1].toNumber(); + qreal x = callData->args[2].toNumber(); + qreal y = callData->args[3].toNumber(); if (!qt_is_finite(cpx) || !qt_is_finite(cpy) || !qt_is_finite(x) || !qt_is_finite(y)) - return ctx->thisObject().asReturnedValue(); + return; r->d()->context->quadraticCurveTo(cpx, cpy, x, y); } - - return ctx->thisObject().asReturnedValue(); } /*! @@ -2454,15 +2414,15 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_quadraticCurveTo(QV4::Call Adds a rectangle at position (\c x, \c y), with the given width \c w and height \c h, as a closed subpath. */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_rect(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_rect(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - if (ctx->argc() >= 4) - r->d()->context->rect(ctx->args()[0].toNumber(), ctx->args()[1].toNumber(), ctx->args()[2].toNumber(), ctx->args()[3].toNumber()); - return ctx->thisObject().asReturnedValue(); + if (callData->argc >= 4) + r->d()->context->rect(callData->args[0].toNumber(), callData->args[1].toNumber(), callData->args[2].toNumber(), callData->args[3].toNumber()); + scope.result = callData->thisObject; + } /*! @@ -2471,20 +2431,20 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_rect(QV4::CallContext *ctx Adds the given rectangle rect with rounded corners to the path. The \c xRadius and \c yRadius arguments specify the radius of the ellipses defining the corners of the rounded rectangle. */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_roundedRect(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_roundedRect(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - if (ctx->argc() >= 6) - r->d()->context->roundedRect(ctx->args()[0].toNumber() - , ctx->args()[1].toNumber() - , ctx->args()[2].toNumber() - , ctx->args()[3].toNumber() - , ctx->args()[4].toNumber() - , ctx->args()[5].toNumber()); - return ctx->thisObject().asReturnedValue(); + if (callData->argc >= 6) + r->d()->context->roundedRect(callData->args[0].toNumber() + , callData->args[1].toNumber() + , callData->args[2].toNumber() + , callData->args[3].toNumber() + , callData->args[4].toNumber() + , callData->args[5].toNumber()); + scope.result = callData->thisObject; + } /*! @@ -2495,17 +2455,17 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_roundedRect(QV4::CallConte The ellipse is composed of a clockwise curve, starting and finishing at zero degrees (the 3 o'clock position). */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_ellipse(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_ellipse(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - if (ctx->argc() >= 4) - r->d()->context->ellipse(ctx->args()[0].toNumber(), ctx->args()[1].toNumber(), ctx->args()[2].toNumber(), ctx->args()[3].toNumber()); + if (callData->argc >= 4) + r->d()->context->ellipse(callData->args[0].toNumber(), callData->args[1].toNumber(), callData->args[2].toNumber(), callData->args[3].toNumber()); + + scope.result = callData->thisObject; - return ctx->thisObject().asReturnedValue(); } /*! @@ -2514,21 +2474,22 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_ellipse(QV4::CallContext * Adds the given \c text to the path as a set of closed subpaths created from the current context font supplied. The subpaths are positioned so that the left end of the text's baseline lies at the point specified by (\c x, \c y). */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_text(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_text(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - if (ctx->argc() >= 3) { - qreal x = ctx->args()[1].toNumber(); - qreal y = ctx->args()[2].toNumber(); + scope.result = callData->thisObject; + + if (callData->argc >= 3) { + qreal x = callData->args[1].toNumber(); + qreal y = callData->args[2].toNumber(); if (!qt_is_finite(x) || !qt_is_finite(y)) - return ctx->thisObject().asReturnedValue(); - r->d()->context->text(ctx->args()[0].toQStringNoThrow(), x, y); + return; + r->d()->context->text(callData->args[0].toQStringNoThrow(), x, y); } - return ctx->thisObject().asReturnedValue(); + } /*! @@ -2540,14 +2501,14 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_text(QV4::CallContext *ctx \sa strokeStyle */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_stroke(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_stroke(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) r->d()->context->stroke(); - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject; + } /*! @@ -2557,37 +2518,30 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_stroke(QV4::CallContext *c \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-ispointinpath}{W3C 2d context standard for isPointInPath} */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_isPointInPath(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_isPointInPath(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) bool pointInPath = false; - if (ctx->argc() >= 2) - pointInPath = r->d()->context->isPointInPath(ctx->args()[0].toNumber(), ctx->args()[1].toNumber()); - return QV4::Primitive::fromBoolean(pointInPath).asReturnedValue(); + if (callData->argc >= 2) + pointInPath = r->d()->context->isPointInPath(callData->args[0].toNumber(), callData->args[1].toNumber()); + scope.result = QV4::Primitive::fromBoolean(pointInPath).asReturnedValue(); } -QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawFocusRing(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_drawFocusRing(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *) { - QV4::Scope scope(ctx); - - V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::drawFocusRing is not supported"); + THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::drawFocusRing is not supported"); } -QV4::ReturnedValue QQuickJSContext2DPrototype::method_setCaretSelectionRect(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_setCaretSelectionRect(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *) { - QV4::Scope scope(ctx); - - V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::setCaretSelectionRect is not supported"); + THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::setCaretSelectionRect is not supported"); } -QV4::ReturnedValue QQuickJSContext2DPrototype::method_caretBlinkRate(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_caretBlinkRate(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *) { - QV4::Scope scope(ctx); - - V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::caretBlinkRate is not supported"); + THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::caretBlinkRate is not supported"); } /*! @@ -2613,29 +2567,27 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_caretBlinkRate(QV4::CallCo The default font value is "10px sans-serif". */ -QV4::ReturnedValue QQuickJSContext2D::method_get_font(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_font(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - return QV4::Encode(scope.engine->newString(r->d()->context->state.font.toString())); + RETURN_RESULT(scope.engine->newString(r->d()->context->state.font.toString())); } -QV4::ReturnedValue QQuickJSContext2D::method_set_font(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_font(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT_SETTER(r) - QV4::ScopedString s(scope, ctx->argument(0), QV4::ScopedString::Convert); + QV4::ScopedString s(scope, callData->argument(0), QV4::ScopedString::Convert); if (scope.engine->hasException) - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); QFont font = qt_font_from_string(s->toQString(), r->d()->context->state.font); if (font != r->d()->context->state.font) { r->d()->context->state.font = font; } - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } /*! @@ -2652,37 +2604,35 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_font(QV4::CallContext *ctx) \endlist Other values are ignored. The default value is "start". */ -QV4::ReturnedValue QQuickJSContext2D::method_get_textAlign(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_textAlign(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) switch (r->d()->context->state.textAlign) { case QQuickContext2D::End: - return QV4::Encode(scope.engine->newString(QStringLiteral("end"))); + RETURN_RESULT(scope.engine->newString(QStringLiteral("end"))); case QQuickContext2D::Left: - return QV4::Encode(scope.engine->newString(QStringLiteral("left"))); + RETURN_RESULT(scope.engine->newString(QStringLiteral("left"))); case QQuickContext2D::Right: - return QV4::Encode(scope.engine->newString(QStringLiteral("right"))); + RETURN_RESULT(scope.engine->newString(QStringLiteral("right"))); case QQuickContext2D::Center: - return QV4::Encode(scope.engine->newString(QStringLiteral("center"))); + RETURN_RESULT(scope.engine->newString(QStringLiteral("center"))); case QQuickContext2D::Start: default: break; } - return QV4::Encode(scope.engine->newString(QStringLiteral("start"))); + RETURN_RESULT(scope.engine->newString(QStringLiteral("start"))); } -QV4::ReturnedValue QQuickJSContext2D::method_set_textAlign(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_textAlign(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT_SETTER(r) - QV4::ScopedString s(scope, ctx->argument(0), QV4::ScopedString::Convert); + QV4::ScopedString s(scope, callData->argument(0), QV4::ScopedString::Convert); if (scope.engine->hasException) - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); QString textAlign = s->toQString(); QQuickContext2D::TextAlignType ta; @@ -2697,12 +2647,12 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_textAlign(QV4::CallContext *ctx else if (textAlign == QLatin1String("center")) ta = QQuickContext2D::Center; else - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); if (ta != r->d()->context->state.textAlign) r->d()->context->state.textAlign = ta; - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } /*! @@ -2720,36 +2670,34 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_textAlign(QV4::CallContext *ctx \endlist Other values are ignored. The default value is "alphabetic". */ -QV4::ReturnedValue QQuickJSContext2D::method_get_textBaseline(QV4::CallContext *ctx) +void QQuickJSContext2D::method_get_textBaseline(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) switch (r->d()->context->state.textBaseline) { case QQuickContext2D::Hanging: - return QV4::Encode(scope.engine->newString(QStringLiteral("hanging"))); + RETURN_RESULT(scope.engine->newString(QStringLiteral("hanging"))); case QQuickContext2D::Top: - return QV4::Encode(scope.engine->newString(QStringLiteral("top"))); + RETURN_RESULT(scope.engine->newString(QStringLiteral("top"))); case QQuickContext2D::Bottom: - return QV4::Encode(scope.engine->newString(QStringLiteral("bottom"))); + RETURN_RESULT(scope.engine->newString(QStringLiteral("bottom"))); case QQuickContext2D::Middle: - return QV4::Encode(scope.engine->newString(QStringLiteral("middle"))); + RETURN_RESULT(scope.engine->newString(QStringLiteral("middle"))); case QQuickContext2D::Alphabetic: default: break; } - return QV4::Encode(scope.engine->newString(QStringLiteral("alphabetic"))); + RETURN_RESULT(scope.engine->newString(QStringLiteral("alphabetic"))); } -QV4::ReturnedValue QQuickJSContext2D::method_set_textBaseline(QV4::CallContext *ctx) +void QQuickJSContext2D::method_set_textBaseline(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT_SETTER(r) - QV4::ScopedString s(scope, ctx->argument(0), QV4::ScopedString::Convert); + QV4::ScopedString s(scope, callData->argument(0), QV4::ScopedString::Convert); if (scope.engine->hasException) - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); QString textBaseline = s->toQString(); QQuickContext2D::TextBaseLineType tb; @@ -2764,12 +2712,12 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_textBaseline(QV4::CallContext * else if (textBaseline == QLatin1String("middle")) tb = QQuickContext2D::Middle; else - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); if (tb != r->d()->context->state.textBaseline) r->d()->context->state.textBaseline = tb; - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } /*! @@ -2780,21 +2728,21 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_textBaseline(QV4::CallContext * \sa textBaseline \sa strokeText */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillText(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_fillText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - if (ctx->argc() >= 3) { - qreal x = ctx->args()[1].toNumber(); - qreal y = ctx->args()[2].toNumber(); + scope.result = callData->thisObject; + + if (callData->argc >= 3) { + qreal x = callData->args[1].toNumber(); + qreal y = callData->args[2].toNumber(); if (!qt_is_finite(x) || !qt_is_finite(y)) - return ctx->thisObject().asReturnedValue(); - QPainterPath textPath = r->d()->context->createTextGlyphs(x, y, ctx->args()[0].toQStringNoThrow()); + return; + QPainterPath textPath = r->d()->context->createTextGlyphs(x, y, callData->args[0].toQStringNoThrow()); r->d()->context->buffer()->fill(textPath); } - return ctx->thisObject().asReturnedValue(); } /*! \qmlmethod object QtQuick::Context2D::strokeText(text, x, y) @@ -2804,15 +2752,15 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillText(QV4::CallContext \sa textBaseline \sa fillText */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeText(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_strokeText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - if (ctx->argc() >= 3) - r->d()->context->drawText(ctx->args()[0].toQStringNoThrow(), ctx->args()[1].toNumber(), ctx->args()[2].toNumber(), false); - return ctx->thisObject().asReturnedValue(); + if (callData->argc >= 3) + r->d()->context->drawText(callData->args[0].toQStringNoThrow(), callData->args[1].toNumber(), callData->args[2].toNumber(), false); + scope.result = callData->thisObject; + } /*! @@ -2821,21 +2769,20 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeText(QV4::CallContex Returns an object with a \c width property, whose value is equivalent to calling \l {QFontMetrics::width()} with the given \a text in the current font. */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_measureText(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_measureText(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) - if (ctx->argc() >= 1) { + if (callData->argc >= 1) { QFontMetrics fm(r->d()->context->state.font); - uint width = fm.width(ctx->args()[0].toQStringNoThrow()); + uint width = fm.width(callData->args[0].toQStringNoThrow()); QV4::ScopedObject tm(scope, scope.engine->newObject()); tm->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("width"))).getPointer(), QV4::ScopedValue(scope, QV4::Primitive::fromDouble(width))); - return tm.asReturnedValue(); + RETURN_RESULT(tm); } - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } // drawing images @@ -2897,28 +2844,29 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_measureText(QV4::CallConte \sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-drawimage}{W3C 2d context standard for drawImage} */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_drawImage(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject()); + QV4::Scoped r(scope, callData->thisObject); CHECK_CONTEXT(r) + scope.result = callData->thisObject; + qreal sx, sy, sw, sh, dx, dy, dw, dh; - if (!ctx->argc()) - return ctx->thisObject().asReturnedValue(); + if (!callData->argc) + return; //FIXME:This function should be moved to QQuickContext2D::drawImage(...) if (!r->d()->context->state.invertibleCTM) - return ctx->thisObject().asReturnedValue(); + return; QQmlRefPointer pixmap; - QV4::ScopedValue arg(scope, ctx->args()[0]); + QV4::ScopedValue arg(scope, callData->args[0]); if (arg->isString()) { QUrl url(arg->toQString()); if (!url.isValid()) - V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); + THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); pixmap = r->d()->context->createPixmap(url); } else if (arg->isObject()) { @@ -2931,7 +2879,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext if (!img.isNull()) pixmap.adopt(new QQuickCanvasPixmap(img)); } else { - V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); + THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); } } else { QV4::Scoped imageData(scope, arg); @@ -2940,44 +2888,44 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext if (pix && !pix->d()->image->isNull()) { pixmap.adopt(new QQuickCanvasPixmap(*pix->d()->image)); } else { - V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); + THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); } } else { QUrl url(arg->toQStringNoThrow()); if (url.isValid()) pixmap = r->d()->context->createPixmap(url); else - V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); + THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); } } } else { - V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); + THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); } if (pixmap.isNull() || !pixmap->isValid()) - return ctx->thisObject().asReturnedValue(); - - if (ctx->argc() >= 9) { - sx = ctx->args()[1].toNumber(); - sy = ctx->args()[2].toNumber(); - sw = ctx->args()[3].toNumber(); - sh = ctx->args()[4].toNumber(); - dx = ctx->args()[5].toNumber(); - dy = ctx->args()[6].toNumber(); - dw = ctx->args()[7].toNumber(); - dh = ctx->args()[8].toNumber(); - } else if (ctx->argc() >= 5) { + return; + + if (callData->argc >= 9) { + sx = callData->args[1].toNumber(); + sy = callData->args[2].toNumber(); + sw = callData->args[3].toNumber(); + sh = callData->args[4].toNumber(); + dx = callData->args[5].toNumber(); + dy = callData->args[6].toNumber(); + dw = callData->args[7].toNumber(); + dh = callData->args[8].toNumber(); + } else if (callData->argc >= 5) { sx = 0; sy = 0; sw = pixmap->width(); sh = pixmap->height(); - dx = ctx->args()[1].toNumber(); - dy = ctx->args()[2].toNumber(); - dw = ctx->args()[3].toNumber(); - dh = ctx->args()[4].toNumber(); - } else if (ctx->argc() >= 3) { - dx = ctx->args()[1].toNumber(); - dy = ctx->args()[2].toNumber(); + dx = callData->args[1].toNumber(); + dy = callData->args[2].toNumber(); + dw = callData->args[3].toNumber(); + dh = callData->args[4].toNumber(); + } else if (callData->argc >= 3) { + dx = callData->args[1].toNumber(); + dy = callData->args[2].toNumber(); sx = 0; sy = 0; sw = pixmap->width(); @@ -2985,7 +2933,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext dw = sw; dh = sh; } else { - return ctx->thisObject().asReturnedValue(); + return; } if (!qt_is_finite(sx) @@ -2996,7 +2944,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext || !qt_is_finite(dy) || !qt_is_finite(dw) || !qt_is_finite(dh)) - return ctx->thisObject().asReturnedValue(); + return; if (sx < 0 || sy < 0 @@ -3005,12 +2953,10 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext || sx + sw > pixmap->width() || sy + sh > pixmap->height() || sx + sw < 0 || sy + sh < 0) { - V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "drawImage(), index size error"); + THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "drawImage(), index size error"); } r->d()->context->buffer()->drawPixmap(pixmap, QRectF(sx, sy, sw, sh), QRectF(dx, dy, dw, dh)); - - return ctx->thisObject().asReturnedValue(); } // pixel manipulation @@ -3037,45 +2983,40 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext \qmlproperty int QtQuick::CanvasImageData::width Holds the actual width dimension of the data in the ImageData object, in device pixels. */ -QV4::ReturnedValue QQuickJSContext2DImageData::method_get_width(QV4::CallContext *ctx) +void QQuickJSContext2DImageData::method_get_width(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped imageData(scope, ctx->thisObject()); + QV4::Scoped imageData(scope, callData->thisObject); if (!imageData) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); QV4::Scoped r(scope, imageData->d()->pixelData.as()); - if (!r) - return QV4::Encode(0); - return QV4::Encode(r->d()->image->width()); + int width = r ? r->d()->image->width() : 0; + scope.result = QV4::Encode(width); } /*! \qmlproperty int QtQuick::CanvasImageData::height Holds the actual height dimension of the data in the ImageData object, in device pixels. */ -QV4::ReturnedValue QQuickJSContext2DImageData::method_get_height(QV4::CallContext *ctx) +void QQuickJSContext2DImageData::method_get_height(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped imageData(scope, ctx->thisObject()); + QV4::Scoped imageData(scope, callData->thisObject); if (!imageData) - return ctx->engine()->throwTypeError(); + THROW_TYPE_ERROR(); QV4::Scoped r(scope, imageData->d()->pixelData.as()); - if (!r) - return QV4::Encode(0); - return QV4::Encode(r->d()->image->height()); + int height = r ? r->d()->image->height() : 0; + scope.result = QV4::Encode(height); } /*! \qmlproperty object QtQuick::CanvasImageData::data Holds the one-dimensional array containing the data in RGBA order, as integers in the range 0 to 255. */ -QV4::ReturnedValue QQuickJSContext2DImageData::method_get_data(QV4::CallContext *ctx) +void QQuickJSContext2DImageData::method_get_data(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped imageData(scope, ctx->thisObject()); + QV4::Scoped imageData(scope, callData->thisObject); if (!imageData) - return ctx->engine()->throwTypeError(); - return imageData->d()->pixelData.asReturnedValue(); + THROW_TYPE_ERROR(); + scope.result = imageData->d()->pixelData; } /*! @@ -3096,14 +3037,13 @@ QV4::ReturnedValue QQuickJSContext2DImageData::method_get_data(QV4::CallContext The length attribute of a CanvasPixelArray object must return this h×w×4 number value. This property is read only. */ -QV4::ReturnedValue QQuickJSContext2DPixelData::proto_get_length(QV4::CallContext *ctx) +void QQuickJSContext2DPixelData::proto_get_length(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); if (!r || r->d()->image->isNull()) - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); - return QV4::Encode(r->d()->image->width() * r->d()->image->height() * 4); + RETURN_RESULT(r->d()->image->width() * r->d()->image->height() * 4); } QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(const QV4::Managed *m, uint index, bool *hasProperty) @@ -3192,108 +3132,107 @@ void QQuickJSContext2DPixelData::putIndexed(QV4::Managed *m, uint index, const Q \sa Canvas::loadImage(), QtQuick::Canvas::unloadImage(), QtQuick::Canvas::isImageLoaded */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_createImageData(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_createImageData(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) - if (ctx->argc() == 1) { - QV4::ScopedValue arg0(scope, ctx->args()[0]); + if (callData->argc == 1) { + QV4::ScopedValue arg0(scope, callData->args[0]); QV4::Scoped imgData(scope, arg0); if (!!imgData) { QV4::Scoped pa(scope, imgData->d()->pixelData.as()); if (pa) { qreal w = pa->d()->image->width(); qreal h = pa->d()->image->height(); - return qt_create_image_data(w, h, scope.engine, QImage()); + RETURN_RESULT(qt_create_image_data(w, h, scope.engine, QImage())); } } else if (arg0->isString()) { QImage image = r->d()->context->createPixmap(QUrl(arg0->toQStringNoThrow()))->image(); - return qt_create_image_data(image.width(), image.height(), scope.engine, image); + RETURN_RESULT(qt_create_image_data(image.width(), image.height(), scope.engine, image)); } - } else if (ctx->argc() == 2) { - qreal w = ctx->args()[0].toNumber(); - qreal h = ctx->args()[1].toNumber(); + } else if (callData->argc == 2) { + qreal w = callData->args[0].toNumber(); + qreal h = callData->args[1].toNumber(); if (!qt_is_finite(w) || !qt_is_finite(h)) - V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createImageData(): invalid arguments"); + THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createImageData(): invalid arguments"); if (w > 0 && h > 0) - return qt_create_image_data(w, h, scope.engine, QImage()); + RETURN_RESULT(qt_create_image_data(w, h, scope.engine, QImage())); else - V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createImageData(): invalid arguments"); + THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createImageData(): invalid arguments"); } - return QV4::Encode::undefined(); + RETURN_UNDEFINED(); } /*! \qmlmethod CanvasImageData QtQuick::Context2D::getImageData(real sx, real sy, real sw, real sh) Returns an CanvasImageData object containing the image data for the given rectangle of the canvas. */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_getImageData(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_getImageData(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) - if (ctx->argc() >= 4) { - qreal x = ctx->args()[0].toNumber(); - qreal y = ctx->args()[1].toNumber(); - qreal w = ctx->args()[2].toNumber(); - qreal h = ctx->args()[3].toNumber(); + if (callData->argc >= 4) { + qreal x = callData->args[0].toNumber(); + qreal y = callData->args[1].toNumber(); + qreal w = callData->args[2].toNumber(); + qreal h = callData->args[3].toNumber(); if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h)) - V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "getImageData(): Invalid arguments"); + THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "getImageData(): Invalid arguments"); if (w <= 0 || h <= 0) - V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "getImageData(): Invalid arguments"); + THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "getImageData(): Invalid arguments"); QImage image = r->d()->context->canvas()->toImage(QRectF(x, y, w, h)); - return qt_create_image_data(w, h, scope.engine, image); + RETURN_RESULT(qt_create_image_data(w, h, scope.engine, image)); } - return QV4::Encode::null(); + scope.result = QV4::Encode::null(); } /*! \qmlmethod object QtQuick::Context2D::putImageData(CanvasImageData imageData, real dx, real dy, real dirtyX, real dirtyY, real dirtyWidth, real dirtyHeight) Paints the data from the given ImageData object onto the canvas. If a dirty rectangle (\a dirtyX, \a dirtyY, \a dirtyWidth, \a dirtyHeight) is provided, only the pixels from that rectangle are painted. */ -QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::CallContext *ctx) +void QQuickJSContext2DPrototype::method_putImageData(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped r(scope, ctx->thisObject().as()); + QV4::Scoped r(scope, callData->thisObject.as()); CHECK_CONTEXT(r) - if (ctx->argc() < 7) - return QV4::Encode::undefined(); + if (callData->argc < 7) + RETURN_UNDEFINED(); - QV4::ScopedValue arg0(scope, ctx->args()[0]); + QV4::ScopedValue arg0(scope, callData->args[0]); if (!arg0->isObject()) - V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "Context2D::putImageData, the image data type mismatch"); + THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "Context2D::putImageData, the image data type mismatch"); - qreal dx = ctx->args()[1].toNumber(); - qreal dy = ctx->args()[2].toNumber(); + qreal dx = callData->args[1].toNumber(); + qreal dy = callData->args[2].toNumber(); qreal w, h, dirtyX, dirtyY, dirtyWidth, dirtyHeight; if (!qt_is_finite(dx) || !qt_is_finite(dy)) - V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments"); + THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments"); + + scope.result = callData->thisObject; QV4::Scoped imageData(scope, arg0); if (!imageData) - return ctx->thisObject().asReturnedValue(); + return; QV4::Scoped pixelArray(scope, imageData->d()->pixelData.as()); if (pixelArray) { w = pixelArray->d()->image->width(); h = pixelArray->d()->image->height(); - if (ctx->argc() == 7) { - dirtyX = ctx->args()[3].toNumber(); - dirtyY = ctx->args()[4].toNumber(); - dirtyWidth = ctx->args()[5].toNumber(); - dirtyHeight = ctx->args()[6].toNumber(); + if (callData->argc == 7) { + dirtyX = callData->args[3].toNumber(); + dirtyY = callData->args[4].toNumber(); + dirtyWidth = callData->args[5].toNumber(); + dirtyHeight = callData->args[6].toNumber(); if (!qt_is_finite(dirtyX) || !qt_is_finite(dirtyY) || !qt_is_finite(dirtyWidth) || !qt_is_finite(dirtyHeight)) - V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments"); + THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments"); if (dirtyWidth < 0) { @@ -3325,7 +3264,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::CallCont } if (dirtyWidth <=0 || dirtyHeight <= 0) - return ctx->thisObject().asReturnedValue(); + return; } else { dirtyX = 0; dirtyY = 0; @@ -3336,7 +3275,6 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::CallCont QImage image = pixelArray->d()->image->copy(dirtyX, dirtyY, dirtyWidth, dirtyHeight); r->d()->context->buffer()->drawImage(image, QRectF(dirtyX, dirtyY, dirtyWidth, dirtyHeight), QRectF(dx, dy, dirtyWidth, dirtyHeight)); } - return ctx->thisObject().asReturnedValue(); } /*! @@ -3359,39 +3297,38 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::CallCont gradient.addColorStop(0.7, 'rgba(0, 255, 255, 1'); \endcode */ -QV4::ReturnedValue QQuickContext2DStyle::gradient_proto_addColorStop(QV4::CallContext *ctx) +void QQuickContext2DStyle::gradient_proto_addColorStop(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { - QV4::Scope scope(ctx); - QV4::Scoped style(scope, ctx->thisObject().as()); + QV4::Scoped style(scope, callData->thisObject.as()); if (!style) - V4THROW_ERROR("Not a CanvasGradient object"); + THROW_GENERIC_ERROR("Not a CanvasGradient object"); - if (ctx->argc() == 2) { + if (callData->argc == 2) { if (!style->d()->brush->gradient()) - V4THROW_ERROR("Not a valid CanvasGradient object, can't get the gradient information"); + THROW_GENERIC_ERROR("Not a valid CanvasGradient object, can't get the gradient information"); QGradient gradient = *(style->d()->brush->gradient()); - qreal pos = ctx->args()[0].toNumber(); + qreal pos = callData->args[0].toNumber(); QColor color; - if (ctx->args()[1].as()) { - color = scope.engine->toVariant(ctx->args()[1], qMetaTypeId()).value(); + if (callData->args[1].as()) { + color = scope.engine->toVariant(callData->args[1], qMetaTypeId()).value(); } else { - color = qt_color_from_string(ctx->args()[1]); + color = qt_color_from_string(callData->args[1]); } if (pos < 0.0 || pos > 1.0 || !qt_is_finite(pos)) { - V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "CanvasGradient: parameter offset out of range"); + THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "CanvasGradient: parameter offset out of range"); } if (color.isValid()) { gradient.setColorAt(pos, color); } else { - V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "CanvasGradient: parameter color is not a valid color string"); + THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "CanvasGradient: parameter color is not a valid color string"); } *style->d()->brush = gradient; } - return ctx->thisObject().asReturnedValue(); + scope.result = callData->thisObject; } void QQuickContext2D::scale(qreal x, qreal y) -- cgit v1.2.3 From b07a6cf8c5788b7e4ca722c9aa8c06e76e688c5d Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 24 Jan 2017 11:45:32 +0100 Subject: Allow more expressions as base/index in IR subscripts Arguments and locals can be used directly as the base of a subscript, so they do not need to be assigned to a temporary first. For indices, arguments, locals, and constants, can be used just fine for subscripts. This reduces a whole lot of assignments to temporaries when generating the IR. Although they will be removed in an optimization pass, they do consume memory for no good reason, and make SSA transformation take more time. Change-Id: Ie2af65b66fecee3e140228a9532c9fab08474f5b Reviewed-by: Simon Hausmann --- src/qml/compiler/qv4codegen.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index e0def1021b..46c27fc735 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -526,21 +526,21 @@ IR::Expr *Codegen::subscript(IR::Expr *base, IR::Expr *index) if (hasError) return 0; - if (! base->asTemp() || base->asArgLocal()) { + if (! base->asTemp() && !base->asArgLocal()) { const unsigned t = _block->newTemp(); move(_block->TEMP(t), base); base = _block->TEMP(t); } - if (! index->asTemp() || index->asArgLocal()) { + if (! index->asTemp() && !index->asArgLocal() && !index->asConst()) { const unsigned t = _block->newTemp(); move(_block->TEMP(t), index); index = _block->TEMP(t); } Q_ASSERT(base->asTemp() || base->asArgLocal()); - Q_ASSERT(index->asTemp() || index->asArgLocal()); - return _block->SUBSCRIPT(base->asTemp(), index->asTemp()); + Q_ASSERT(index->asTemp() || index->asArgLocal() || index->asConst()); + return _block->SUBSCRIPT(base, index); } IR::Expr *Codegen::argument(IR::Expr *expr) -- cgit v1.2.3 From 3ca8c880c163708757a5e88fb7e01268b775dc0e Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 24 Jan 2017 11:45:40 +0100 Subject: Allow constants in IR as binop operands There is no reason not to do this, plus it only takes up memory (for assignment to temporaries) and makes SSA transformation more costly. Change-Id: I09edbabe6ed50ab1a61b29ebd2ab541bccc95fad Reviewed-by: Lars Knoll --- src/qml/compiler/qv4codegen.cpp | 10 +++++----- src/qml/jit/qv4isel_masm.cpp | 7 +++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 46c27fc735..d9c1e90125 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -611,7 +611,7 @@ IR::Expr *Codegen::binop(IR::AluOp op, IR::Expr *left, IR::Expr *right, const AS if (IR::Const *c1 = left->asConst()) { if (IR::Const *c2 = right->asConst()) { - if (c1->type == IR::NumberType && c2->type == IR::NumberType) { + if ((c1->type & IR::NumberType) && (c2->type & IR::NumberType)) { switch (op) { case IR::OpAdd: return _block->CONST(IR::NumberType, c1->value + c2->value); case IR::OpAnd: return _block->CONST(IR::BoolType, c1->value ? c2->value : 0); @@ -659,20 +659,20 @@ IR::Expr *Codegen::binop(IR::AluOp op, IR::Expr *left, IR::Expr *right, const AS } } - if (!left->asTemp() && !left->asArgLocal()) { + if (!left->asTemp() && !left->asArgLocal() && !left->asConst()) { const unsigned t = _block->newTemp(); setLocation(move(_block->TEMP(t), left), loc); left = _block->TEMP(t); } - if (!right->asTemp() && !right->asArgLocal()) { + if (!right->asTemp() && !right->asArgLocal() && !right->asConst()) { const unsigned t = _block->newTemp(); setLocation(move(_block->TEMP(t), right), loc); right = _block->TEMP(t); } - Q_ASSERT(left->asTemp() || left->asArgLocal()); - Q_ASSERT(right->asTemp() || right->asArgLocal()); + Q_ASSERT(left->asTemp() || left->asArgLocal() || left->asConst()); + Q_ASSERT(right->asTemp() || right->asArgLocal() || right->asConst()); return _block->BINOP(op, left, right); } diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index 20752b5c34..279ccabf81 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -1712,6 +1712,13 @@ bool InstructionSelection::visitCJumpStrictBool(IR::Binop *binop, IR::BasicBlock // neither operands are statically typed as bool, so bail out. return false; } + if (otherSrc->type == IR::UnknownType) { + // Ok, we really need to call into the runtime. + // (This case doesn't happen when the optimizer ran, because everything will be typed (yes, + // possibly as "var" meaning anything), but it does happen for $0===true, which is generated + // for things where the optimizer didn't run (like functions with a try block).) + return false; + } Assembler::RelationalCondition cond = binop->op == IR::OpStrictEqual ? Assembler::Equal : Assembler::NotEqual; -- cgit v1.2.3 From 5ef3265cd46de6579399562429e26961d6f13885 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Sun, 22 Jan 2017 20:22:14 +0100 Subject: Add anisotropic filtering support to QSGTexture This patch adds support to switch on anisotropic filtering on QSGTexture and to QSGDefaultImageNode. Not adding this support to QSGImageNode since it became public in 5.8, and it does not allow additional virtual methods anymore. Change-Id: Ibf1744845df2297f9129b1b5ce6a69d0a3b31c7c Reviewed-by: Andy Nichols Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/util/qsgdefaultimagenode.cpp | 15 +++++++ src/quick/scenegraph/util/qsgdefaultimagenode_p.h | 4 ++ src/quick/scenegraph/util/qsgimagenode.h | 2 + src/quick/scenegraph/util/qsgtexture.cpp | 53 +++++++++++++++++++++++ src/quick/scenegraph/util/qsgtexture.h | 11 +++++ src/quick/scenegraph/util/qsgtexture_p.h | 2 + src/quick/scenegraph/util/qsgtexturematerial.cpp | 2 + src/quick/scenegraph/util/qsgtexturematerial.h | 7 ++- 8 files changed, 94 insertions(+), 2 deletions(-) diff --git a/src/quick/scenegraph/util/qsgdefaultimagenode.cpp b/src/quick/scenegraph/util/qsgdefaultimagenode.cpp index 63773887a0..7186ee4265 100644 --- a/src/quick/scenegraph/util/qsgdefaultimagenode.cpp +++ b/src/quick/scenegraph/util/qsgdefaultimagenode.cpp @@ -94,6 +94,21 @@ QSGTexture::Filtering QSGDefaultImageNode::mipmapFiltering() const return m_material.mipmapFiltering(); } +void QSGDefaultImageNode::setAnisotropyLevel(QSGTexture::AnisotropyLevel level) +{ + if (m_material.anisotropyLevel() == level) + return; + + m_material.setAnisotropyLevel(level); + m_opaque_material.setAnisotropyLevel(level); + markDirty(DirtyMaterial); +} + +QSGTexture::AnisotropyLevel QSGDefaultImageNode::anisotropyLevel() const +{ + return m_material.anisotropyLevel(); +} + void QSGDefaultImageNode::setRect(const QRectF &r) { if (m_rect == r) diff --git a/src/quick/scenegraph/util/qsgdefaultimagenode_p.h b/src/quick/scenegraph/util/qsgdefaultimagenode_p.h index bb9ebec885..cb23e759d3 100644 --- a/src/quick/scenegraph/util/qsgdefaultimagenode_p.h +++ b/src/quick/scenegraph/util/qsgdefaultimagenode_p.h @@ -85,6 +85,10 @@ public: void setOwnsTexture(bool owns) override; bool ownsTexture() const override; + // QSGImageNode now being a public class does not allow any additional virtual methods. Placing these here, non-virtual. + void setAnisotropyLevel(QSGTexture::AnisotropyLevel level); + QSGTexture::AnisotropyLevel anisotropyLevel() const; + private: QSGGeometry m_geometry; QSGOpaqueTextureMaterial m_opaque_material; diff --git a/src/quick/scenegraph/util/qsgimagenode.h b/src/quick/scenegraph/util/qsgimagenode.h index d25e732e4b..0e053c307f 100644 --- a/src/quick/scenegraph/util/qsgimagenode.h +++ b/src/quick/scenegraph/util/qsgimagenode.h @@ -67,6 +67,8 @@ public: virtual void setMipmapFiltering(QSGTexture::Filtering filtering) = 0; virtual QSGTexture::Filtering mipmapFiltering() const = 0; + // ### Qt6: Add anisotropy support here, and possibly a virtual hook or another mean to extend this class. + enum TextureCoordinatesTransformFlag { NoTransform = 0x00, MirrorHorizontally = 0x01, diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp index 47248f2f37..bc59c49162 100644 --- a/src/quick/scenegraph/util/qsgtexture.cpp +++ b/src/quick/scenegraph/util/qsgtexture.cpp @@ -83,6 +83,9 @@ static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK" #define GL_BGRA 0x80E1 #endif +#ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#endif QT_BEGIN_NAMESPACE @@ -97,10 +100,12 @@ inline static bool isPowerOfTwo(int x) QSGTexturePrivate::QSGTexturePrivate() : wrapChanged(false) , filteringChanged(false) + , anisotropyChanged(false) , horizontalWrap(QSGTexture::ClampToEdge) , verticalWrap(QSGTexture::ClampToEdge) , mipmapMode(QSGTexture::None) , filterMode(QSGTexture::Nearest) + , anisotropyLevel(QSGTexture::AnisotropyNone) { } @@ -273,6 +278,23 @@ static void qt_debug_remove_texture(QSGTexture* texture) neighboring texels. */ +/*! + \enum QSGTexture::AnisotropyLevel + + Specifies the anisotropic filtering level to be used when + the texture is not screen aligned. + + \value AnisotropyNone No anisotropic filtering. + + \value Anisotropy2x 2x anisotropic filtering. + + \value Anisotropy4x 4x anisotropic filtering. + + \value Anisotropy8x 8x anisotropic filtering. + + \value Anisotropy16x 16x anisotropic filtering. +*/ + /*! \fn QSGTexture::QSGTexture(QSGTexturePrivate &dd) \internal @@ -472,6 +494,31 @@ QSGTexture::Filtering QSGTexture::filtering() const return (QSGTexture::Filtering) d_func()->filterMode; } +/*! + Sets the level of anisotropic filtering to be used for the upcoming bind() call to \a level. + The default value is QSGTexture::AnisotropyNone, which means no anisotropic filtering is enabled. + + \since 5.9 + */ +void QSGTexture::setAnisotropyLevel(AnisotropyLevel level) +{ + Q_D(QSGTexture); + if (d->anisotropyLevel != (uint) level) { + d->anisotropyLevel = level; + d->anisotropyChanged = true; + } +} + +/*! + Returns the anisotropy level in use for filtering this texture. + + \since 5.9 + */ +QSGTexture::AnisotropyLevel QSGTexture::anisotropyLevel() const +{ + return (QSGTexture::AnisotropyLevel) d_func()->anisotropyLevel; +} + /*! @@ -548,6 +595,12 @@ void QSGTexture::updateBindOptions(bool force) d->filteringChanged = false; } + if (force || d->anisotropyChanged) { + d->anisotropyChanged = false; + if (QOpenGLContext::currentContext()->hasExtension(QByteArrayLiteral("GL_EXT_texture_filter_anisotropic"))) + funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, float(1 << (d->anisotropyLevel))); + } + if (force || d->wrapChanged) { #ifndef QT_NO_DEBUG if (d->horizontalWrap == Repeat || d->verticalWrap == Repeat) { diff --git a/src/quick/scenegraph/util/qsgtexture.h b/src/quick/scenegraph/util/qsgtexture.h index f0509b58ae..035acc02b1 100644 --- a/src/quick/scenegraph/util/qsgtexture.h +++ b/src/quick/scenegraph/util/qsgtexture.h @@ -67,6 +67,14 @@ public: Linear }; + enum AnisotropyLevel { + AnisotropyNone, + Anisotropy2x, + Anisotropy4x, + Anisotropy8x, + Anisotropy16x + }; + virtual int textureId() const = 0; virtual QSize textureSize() const = 0; virtual bool hasAlphaChannel() const = 0; @@ -87,6 +95,9 @@ public: void setFiltering(Filtering filter); QSGTexture::Filtering filtering() const; + void setAnisotropyLevel(AnisotropyLevel level); + QSGTexture::AnisotropyLevel anisotropyLevel() const; + void setHorizontalWrapMode(WrapMode hwrap); QSGTexture::WrapMode horizontalWrapMode() const; diff --git a/src/quick/scenegraph/util/qsgtexture_p.h b/src/quick/scenegraph/util/qsgtexture_p.h index b6fcfc31c4..36f9b802ba 100644 --- a/src/quick/scenegraph/util/qsgtexture_p.h +++ b/src/quick/scenegraph/util/qsgtexture_p.h @@ -69,11 +69,13 @@ public: uint wrapChanged : 1; uint filteringChanged : 1; + uint anisotropyChanged : 1; uint horizontalWrap : 1; uint verticalWrap : 1; uint mipmapMode : 2; uint filterMode : 2; + uint anisotropyLevel: 3; }; class Q_QUICK_PRIVATE_EXPORT QSGPlainTexture : public QSGTexture diff --git a/src/quick/scenegraph/util/qsgtexturematerial.cpp b/src/quick/scenegraph/util/qsgtexturematerial.cpp index 9326ea640d..c536445e82 100644 --- a/src/quick/scenegraph/util/qsgtexturematerial.cpp +++ b/src/quick/scenegraph/util/qsgtexturematerial.cpp @@ -110,6 +110,7 @@ void QSGOpaqueTextureMaterialShader::updateState(const RenderState &state, QSGMa Q_UNUSED(state) #endif t->setMipmapFiltering(tx->mipmapFiltering()); + t->setAnisotropyLevel(tx->anisotropyLevel()); if (oldTx == 0 || oldTx->texture()->textureId() != t->textureId()) t->bind(); @@ -173,6 +174,7 @@ QSGOpaqueTextureMaterial::QSGOpaqueTextureMaterial() , m_mipmap_filtering(QSGTexture::None) , m_horizontal_wrap(QSGTexture::ClampToEdge) , m_vertical_wrap(QSGTexture::ClampToEdge) + , m_anisotropy_level(QSGTexture::AnisotropyNone) { } diff --git a/src/quick/scenegraph/util/qsgtexturematerial.h b/src/quick/scenegraph/util/qsgtexturematerial.h index dc87131773..87d8e5fd49 100644 --- a/src/quick/scenegraph/util/qsgtexturematerial.h +++ b/src/quick/scenegraph/util/qsgtexturematerial.h @@ -69,6 +69,9 @@ public: void setVerticalWrapMode(QSGTexture::WrapMode mode) { m_vertical_wrap = mode; } QSGTexture::WrapMode verticalWrapMode() const { return QSGTexture::WrapMode(m_vertical_wrap); } + void setAnisotropyLevel(QSGTexture::AnisotropyLevel level) { m_anisotropy_level = level; } + QSGTexture::AnisotropyLevel anisotropyLevel() const { return QSGTexture::AnisotropyLevel(m_anisotropy_level); } + protected: QSGTexture *m_texture; @@ -76,8 +79,8 @@ protected: uint m_mipmap_filtering: 2; uint m_horizontal_wrap : 1; uint m_vertical_wrap: 1; - - uint m_reserved : 26; + uint m_anisotropy_level : 3; + uint m_reserved : 23; }; -- cgit v1.2.3 From 7adf9caa6fd7886e2eead6e8fdc20dea2152a30b Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 25 Jan 2017 12:16:54 +0100 Subject: Ensure that we never create empty MemberData objects They don't make sense. Also fixes a crash in test262, where we would pass n == 0 to MemberData::allocate(). Change-Id: Ia95ab6632bd1998afe84a38c38c3c6603230362d Reviewed-by: Erik Verbruggen --- src/qml/jsruntime/qv4argumentsobject.cpp | 10 ++++++---- src/qml/jsruntime/qv4memberdata.cpp | 1 + src/qml/jsruntime/qv4object.cpp | 2 +- src/qml/qml/qqmlvmemetaobject.cpp | 9 ++++++--- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 5a190d6690..9354bcb1a3 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -88,10 +88,12 @@ void ArgumentsObject::fullyCreate() Scope scope(engine()); Scoped md(scope, d()->mappedArguments); - d()->mappedArguments = md->allocate(engine(), numAccessors); - for (uint i = 0; i < numAccessors; ++i) { - d()->mappedArguments->data[i] = context()->callData->args[i]; - arraySet(i, context()->engine->argumentsAccessors + i, Attr_Accessor); + if (numAccessors) { + d()->mappedArguments = md->allocate(engine(), numAccessors); + for (uint i = 0; i < numAccessors; ++i) { + d()->mappedArguments->data[i] = context()->callData->args[i]; + arraySet(i, context()->engine->argumentsAccessors + i, Attr_Accessor); + } } arrayPut(numAccessors, context()->callData->args + numAccessors, argCount - numAccessors); for (uint i = numAccessors; i < argCount; ++i) diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp index f2a24f8179..db45c77472 100644 --- a/src/qml/jsruntime/qv4memberdata.cpp +++ b/src/qml/jsruntime/qv4memberdata.cpp @@ -55,6 +55,7 @@ void MemberData::markObjects(Heap::Base *that, ExecutionEngine *e) Heap::MemberData *MemberData::allocate(ExecutionEngine *e, uint n, Heap::MemberData *old) { Q_ASSERT(!old || old->size < n); + Q_ASSERT(n); size_t alloc = MemoryManager::align(sizeof(Heap::MemberData) + (n - 1)*sizeof(Value)); Heap::MemberData *m = e->memoryManager->allocManaged(alloc); diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 5d6c479477..eb9cb80cee 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -61,7 +61,7 @@ DEFINE_OBJECT_VTABLE(Object); void Object::setInternalClass(InternalClass *ic) { d()->internalClass = ic; - if (!d()->memberData || (d()->memberData->size < ic->size)) + if ((!d()->memberData && ic->size) || (d()->memberData->size < ic->size)) d()->memberData = MemberData::allocate(ic->engine, ic->size, d()->memberData); } diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 545daa96f8..490a4e19ab 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -325,9 +325,12 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj, if (compiledObject->nProperties || compiledObject->nFunctions) { Q_ASSERT(cache && cache->engine); QV4::ExecutionEngine *v4 = cache->engine; - QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, compiledObject->nProperties + compiledObject->nFunctions); - propertyAndMethodStorage.set(v4, data); - std::fill(data->data, data->data + data->size, QV4::Encode::undefined()); + uint size = compiledObject->nProperties + compiledObject->nFunctions; + if (size) { + QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, size); + propertyAndMethodStorage.set(v4, data); + std::fill(data->data, data->data + data->size, QV4::Encode::undefined()); + } // Need JS wrapper to ensure properties/methods are marked. ensureQObjectWrapper(); -- cgit v1.2.3 From 68bd6fcc8a71400138f92a6454b850104b9da88c Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 25 Jan 2017 12:33:51 +0100 Subject: UINT_MAX is not a valid array index in JS Fix a regression, where we'd accept UINT_MAX as a valid array index. Change-Id: I5ae8874d590f5e99da2e12d367b6f3c65b2bad0b Reviewed-by: Erik Verbruggen --- src/qml/jsruntime/qv4value_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 816b8fb11b..64f0f3a86f 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -544,7 +544,7 @@ inline bool Value::asArrayIndex(uint &idx) const } double d = doubleValue(); idx = (uint)d; - return (idx == d); + return (idx == d && idx != UINT_MAX); } #endif -- cgit v1.2.3 From 898f67ca3b2b727ab7f4f4e74f10a8daed19365b Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 24 Jan 2017 11:45:47 +0100 Subject: Directly assign initializers to variables in variable declarations .. instead of first assigning to a temporary and then assigning the temporary to the argument/local. Change-Id: I15a6c2073b78c5cfc829c7edef07c6bf48be7886 Reviewed-by: Lars Knoll --- src/qml/compiler/qv4codegen.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index d9c1e90125..7d3ad38f97 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -842,9 +842,16 @@ void Codegen::variableDeclaration(VariableDeclaration *ast) Q_ASSERT(expr.code); initializer = *expr; - int initialized = _block->newTemp(); - move(_block->TEMP(initialized), initializer); - move(identifier(ast->name.toString(), ast->identifierToken.startLine, ast->identifierToken.startColumn), _block->TEMP(initialized)); + IR::Expr *lhs = identifier(ast->name.toString(), ast->identifierToken.startLine, + ast->identifierToken.startColumn); + + if (lhs->asArgLocal()) { + move(lhs, initializer); + } else { + int initialized = _block->newTemp(); + move(_block->TEMP(initialized), initializer); + move(lhs, _block->TEMP(initialized)); + } } void Codegen::variableDeclarationList(VariableDeclarationList *ast) -- cgit v1.2.3 From be00fb4bff6d0ceac34a66254466474a6919d0b9 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 25 Jan 2017 15:56:09 +0100 Subject: qml: Rename importCache vars to typeNameCache This better reflects what it is, and especially removes some confusion in QQmlTypeCompiler which has a m_importCache member (of type QQmlImports), which lead to some strange-to-read things like this: m_importCache.populateCache(*importCache); Which is now: m_importCache.populateCache(*typeNameCache); Change-Id: I7590dd1ba71ca77a8d964250a0d517156b723f8e Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmltypecompiler.cpp | 8 +++--- src/qml/compiler/qqmltypecompiler_p.h | 4 +-- src/qml/compiler/qv4compileddata.cpp | 2 +- src/qml/compiler/qv4compileddata_p.h | 2 +- src/qml/qml/qqmlobjectcreator.cpp | 4 +-- src/qml/qml/qqmltypeloader.cpp | 48 +++++++++++++++++------------------ src/qml/qml/qqmltypeloader_p.h | 8 +++--- 7 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index ab2b0553a9..85267225be 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -57,12 +57,12 @@ QT_BEGIN_NAMESPACE QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, - QmlIR::Document *parsedQML, const QQmlRefPointer &importCache, + QmlIR::Document *parsedQML, const QQmlRefPointer &typeNameCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache) : resolvedTypes(resolvedTypeCache) , engine(engine) , typeData(typeData) - , importCache(importCache) + , typeNameCache(typeNameCache) , document(parsedQML) { } @@ -138,7 +138,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() sss.scan(); } - QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsModule, &document->jsParserEngine, document->program, importCache, &document->jsGenerator.stringTable); + QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsModule, &document->jsParserEngine, document->program, typeNameCache, &document->jsGenerator.stringTable); QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator); if (!jsCodeGen.generateCodeForComponents()) return nullptr; @@ -164,7 +164,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() QV4::CompiledData::CompilationUnit *compilationUnit = document->javaScriptCompilationUnit; compilationUnit = document->javaScriptCompilationUnit; - compilationUnit->importCache = importCache; + compilationUnit->typeNameCache = typeNameCache; compilationUnit->resolvedTypes = resolvedTypes; compilationUnit->propertyCaches = std::move(m_propertyCaches); Q_ASSERT(compilationUnit->propertyCaches.count() == static_cast(compilationUnit->data->nObjects)); diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h index de6abb4ced..2b59e7e42f 100644 --- a/src/qml/compiler/qqmltypecompiler_p.h +++ b/src/qml/compiler/qqmltypecompiler_p.h @@ -89,7 +89,7 @@ struct QQmlTypeCompiler { Q_DECLARE_TR_FUNCTIONS(QQmlTypeCompiler) public: - QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document, const QQmlRefPointer &importCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache); + QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document, const QQmlRefPointer &typeNameCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache); // --- interface used by QQmlPropertyCacheCreator typedef QmlIR::Object CompiledObject; @@ -139,7 +139,7 @@ private: QList errors; QQmlEnginePrivate *engine; QQmlTypeData *typeData; - QQmlRefPointer importCache; + QQmlRefPointer typeNameCache; QmlIR::Document *document; // index is string index of type name (use obj->inheritedTypeNameIndex) QHash customParsers; diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 6aac111897..25b090f555 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -207,7 +207,7 @@ void CompilationUnit::unlink() dependentScripts.at(ii)->release(); dependentScripts.clear(); - importCache = nullptr; + typeNameCache = nullptr; qDeleteAll(resolvedTypes); resolvedTypes.clear(); diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 2682365182..97623b4d86 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -855,7 +855,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount QQmlPropertyCacheVector propertyCaches; QQmlPropertyCache *rootPropertyCache() const { return propertyCaches.at(data->indexOfRootObject); } - QQmlRefPointer importCache; + QQmlRefPointer typeNameCache; // index is object index. This allows fast access to the // property data when initializing bindings, avoiding expensive diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 38a16b8cde..85fbd86dc4 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -170,7 +170,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI context = new QQmlContextData; context->isInternal = true; - context->imports = compilationUnit->importCache; + context->imports = compilationUnit->typeNameCache; context->initFromTypeCompilationUnit(compilationUnit, subComponentIndex); context->setParent(parentContext); @@ -1150,7 +1150,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo if (customParser && obj->flags & QV4::CompiledData::Object::HasCustomParserBindings) { customParser->engine = QQmlEnginePrivate::get(engine); - customParser->imports = compilationUnit->importCache; + customParser->imports = compilationUnit->typeNameCache; QList bindings; const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index); diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 5b1bba46dd..13ad02f7cb 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2127,11 +2127,11 @@ bool QQmlTypeData::tryLoadFromDiskCache() return true; } -void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer &importCache, +void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer &typeNameCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache) { Q_ASSERT(m_compiledData); - m_compiledData->importCache = importCache; + m_compiledData->typeNameCache = typeNameCache; m_compiledData->resolvedTypes = resolvedTypeCache; QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine()); @@ -2217,10 +2217,10 @@ void QQmlTypeData::done() } } - QQmlRefPointer importCache; + QQmlRefPointer typeNameCache; QV4::CompiledData::ResolvedTypeReferenceMap resolvedTypeCache; { - QQmlCompileError error = buildTypeResolutionCaches(&importCache, &resolvedTypeCache); + QQmlCompileError error = buildTypeResolutionCaches(&typeNameCache, &resolvedTypeCache); if (error.isSet()) { setError(error); return; @@ -2240,9 +2240,9 @@ void QQmlTypeData::done() if (!m_document.isNull()) { // Compile component - compile(importCache, resolvedTypeCache); + compile(typeNameCache, resolvedTypeCache); } else { - createTypeAndPropertyCaches(importCache, resolvedTypeCache); + createTypeAndPropertyCaches(typeNameCache, resolvedTypeCache); } if (isError()) @@ -2303,7 +2303,7 @@ void QQmlTypeData::done() qualifier = qualifier.mid(lastDotIndex+1); } - m_compiledData->importCache->add(qualifier.toString(), scriptIndex, enclosingNamespace); + m_compiledData->typeNameCache->add(qualifier.toString(), scriptIndex, enclosingNamespace); QQmlScriptData *scriptData = script.script->scriptData(); scriptData->addref(); m_compiledData->dependentScripts << scriptData; @@ -2489,12 +2489,12 @@ QString QQmlTypeData::stringAt(int index) const return m_document->jsGenerator.stringTable.stringForIndex(index); } -void QQmlTypeData::compile(const QQmlRefPointer &importCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache) +void QQmlTypeData::compile(const QQmlRefPointer &typeNameCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache) { Q_ASSERT(m_compiledData.isNull()); QQmlEnginePrivate * const enginePrivate = QQmlEnginePrivate::get(typeLoader()->engine()); - QQmlTypeCompiler compiler(enginePrivate, this, m_document.data(), importCache, resolvedTypeCache); + QQmlTypeCompiler compiler(enginePrivate, this, m_document.data(), typeNameCache, resolvedTypeCache); m_compiledData = compiler.compile(); if (!m_compiledData) { setError(compiler.compilationErrors()); @@ -2598,20 +2598,20 @@ void QQmlTypeData::resolveTypes() } QQmlCompileError QQmlTypeData::buildTypeResolutionCaches( - QQmlRefPointer *importCache, + QQmlRefPointer *typeNameCache, QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache ) const { - importCache->adopt(new QQmlTypeNameCache); + typeNameCache->adopt(new QQmlTypeNameCache); for (const QString &ns: m_namespaces) - (*importCache)->add(ns); + (*typeNameCache)->add(ns); // Add any Composite Singletons that were used to the import cache for (const QQmlTypeData::TypeReference &singleton: m_compositeSingletons) - (*importCache)->add(singleton.type->qmlTypeName(), singleton.type->sourceUrl(), singleton.prefix); + (*typeNameCache)->add(singleton.type->qmlTypeName(), singleton.type->sourceUrl(), singleton.prefix); - m_importCache.populateCache(*importCache); + m_importCache.populateCache(*typeNameCache); QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine()); @@ -2710,7 +2710,7 @@ void QQmlTypeData::scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData: } QQmlScriptData::QQmlScriptData() - : importCache(0) + : typeNameCache(0) , m_loaded(false) , m_program(0) { @@ -2767,8 +2767,8 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent // For backward compatibility, if there are no imports, we need to use the // imports from the parent context. See QTBUG-17518. - if (!importCache->isEmpty()) { - ctxt->imports = importCache; + if (!typeNameCache->isEmpty()) { + ctxt->imports = typeNameCache; } else if (effectiveCtxt) { ctxt->imports = effectiveCtxt->imports; ctxt->importedScripts = effectiveCtxt->importedScripts; @@ -2823,9 +2823,9 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent void QQmlScriptData::clear() { - if (importCache) { - importCache->release(); - importCache = 0; + if (typeNameCache) { + typeNameCache->release(); + typeNameCache = 0; } for (int ii = 0; ii < scripts.count(); ++ii) @@ -2946,7 +2946,7 @@ void QQmlScriptBlob::done() } } - m_scriptData->importCache = new QQmlTypeNameCache(); + m_scriptData->typeNameCache = new QQmlTypeNameCache(); QSet ns; @@ -2958,13 +2958,13 @@ void QQmlScriptBlob::done() if (!script.nameSpace.isNull()) { if (!ns.contains(script.nameSpace)) { ns.insert(script.nameSpace); - m_scriptData->importCache->add(script.nameSpace); + m_scriptData->typeNameCache->add(script.nameSpace); } } - m_scriptData->importCache->add(script.qualifier, scriptIndex, script.nameSpace); + m_scriptData->typeNameCache->add(script.qualifier, scriptIndex, script.nameSpace); } - m_importCache.populateCache(m_scriptData->importCache); + m_importCache.populateCache(m_scriptData->typeNameCache); } QString QQmlScriptBlob::stringAt(int index) const diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index c60435a2d6..14141db180 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -449,12 +449,12 @@ private: void continueLoadFromIR(); void resolveTypes(); QQmlCompileError buildTypeResolutionCaches( - QQmlRefPointer *importCache, + QQmlRefPointer *typeNameCache, QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache ) const; - void compile(const QQmlRefPointer &importCache, + void compile(const QQmlRefPointer &typeNameCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache); - void createTypeAndPropertyCaches(const QQmlRefPointer &importCache, + void createTypeAndPropertyCaches(const QQmlRefPointer &typeNameCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache); bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref, int lineNumber = -1, int columnNumber = -1, bool reportErrors = true); @@ -504,7 +504,7 @@ public: QUrl url; QString urlString; - QQmlTypeNameCache *importCache; + QQmlTypeNameCache *typeNameCache; QList scripts; QV4::ReturnedValue scriptValueForContext(QQmlContextData *parentCtxt); -- cgit v1.2.3 From b90ea664c97894fcd6b912c171e513a3c3977ab4 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 25 Jan 2017 16:12:56 +0100 Subject: QQmlMetaType: Fix an invalid comment No such function as qmlRegisterCompositeType. Change-Id: I0a8faef8a707b64958a7023136a36853a99b7f0a Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlmetatype.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 520c44f4da..bd6b9a1599 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -79,7 +79,7 @@ struct QQmlMetaTypeData Files urlToNonFileImportType; // For non-file imported composite and composite // singleton types. This way we can locate any // of them by url, even if it was registered as - // a module via qmlRegisterCompositeType. + // a module via QQmlPrivate::RegisterCompositeType typedef QHash MetaObjects; MetaObjects metaObjectToType; typedef QHash StringConverters; -- cgit v1.2.3 From f936219fb7d92d91a63785e57b618bfcaa4113ce Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 25 Jan 2017 19:19:35 +0100 Subject: QQmlImport: Clean up & rename getTypeForUrl to fetchOrCreateTypeForUrl The new name better matches what the method does. At the same time, clean it up a little: make the flow a little clearer, extrapolate on some comments, remove some old debug. Also add a small method doc explaining this method does. Change-Id: I494efc2dfe8760734f228a9af440abf7067354b7 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlimport.cpp | 100 ++++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 34 deletions(-) diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 8712b638c5..659c7f1b9f 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -130,42 +130,74 @@ bool isPathAbsolute(const QString &path) #endif } -// If the type does not already exist as a file import, add the type and return the new type -QQmlType *getTypeForUrl(const QString &urlString, const QHashedStringRef& typeName, +/* + \internal + + Fetches the QQmlType instance registered for \a urlString, creating a + registration for it if it is not already registered, using the associated + \a typeName, \a isCompositeSingleton, \a majorVersion and \a minorVersion + details. + + Errors (if there are any) are placed into \a errors, if it is nonzero. Note + that errors are treated as fatal if \a errors is not set. +*/ +QQmlType *fetchOrCreateTypeForUrl(const QString &urlString, const QHashedStringRef& typeName, bool isCompositeSingleton, QList *errors, int majorVersion=-1, int minorVersion=-1) { - QUrl url(urlString); + QUrl url(urlString); // ### unfortunate (costly) conversion QQmlType *ret = QQmlMetaType::qmlType(url); - if (!ret) { //QQmlType not yet existing for composite or composite singleton type - int dot = typeName.indexOf(QLatin1Char('.')); - QHashedStringRef unqualifiedtype = dot < 0 ? typeName : QHashedStringRef(typeName.constData() + dot + 1, typeName.length() - dot - 1); - - //XXX: The constData of the string ref is pointing somewhere unsafe in qmlregister, so we need to create a temporary copy - QByteArray buf(unqualifiedtype.toString().toUtf8()); - - if (isCompositeSingleton) { - QQmlPrivate::RegisterCompositeSingletonType reg = { - url, - "", //Empty URI indicates loaded via file imports - majorVersion, - minorVersion, - buf.constData() - }; - ret = QQmlMetaType::qmlTypeFromIndex(QQmlPrivate::qmlregister(QQmlPrivate::CompositeSingletonRegistration, ®)); - } else { - QQmlPrivate::RegisterCompositeType reg = { - url, - "", //Empty URI indicates loaded via file imports - majorVersion, - minorVersion, - buf.constData() - }; - ret = QQmlMetaType::qmlTypeFromIndex(QQmlPrivate::qmlregister(QQmlPrivate::CompositeRegistration, ®)); - } + if (ret) + return ret; + + int dot = typeName.indexOf(QLatin1Char('.')); + QHashedStringRef unqualifiedtype = dot < 0 ? typeName : QHashedStringRef(typeName.constData() + dot + 1, typeName.length() - dot - 1); + + // We need a pointer, but we were passed a string. Take a copy so we + // can guarentee it will live long enough to reach qmlregister. + QByteArray buf(unqualifiedtype.toString().toUtf8()); + + // Register the type. Note that the URI parameters here are empty; for + // file type imports, we do not place them in a URI as we don't + // necessarily have a good and unique one (picture a library import, + // which may be found in multiple plugin locations on disk), but there + // are other reasons for this too. + // + // By not putting them in a URI, we prevent the types from being + // registered on a QQmlTypeModule; this is important, as once types are + // placed on there, they cannot be easily removed, meaning if the + // developer subsequently loads a different import (meaning different + // types) with the same URI (using, say, a different plugin path), it is + // very undesirable that we continue to associate the types from the + // "old" URI with that new module. + // + // Not having URIs also means that the types cannot be found by name + // etc, the only way to look them up is through QQmlImports -- for + // better or worse. + if (isCompositeSingleton) { + QQmlPrivate::RegisterCompositeSingletonType reg = { + url, + "", // uri + majorVersion, + minorVersion, + buf.constData() + }; + ret = QQmlMetaType::qmlTypeFromIndex(QQmlPrivate::qmlregister(QQmlPrivate::CompositeSingletonRegistration, ®)); + } else { + QQmlPrivate::RegisterCompositeType reg = { + url, + "", // uri + majorVersion, + minorVersion, + buf.constData() + }; + ret = QQmlMetaType::qmlTypeFromIndex(QQmlPrivate::qmlregister(QQmlPrivate::CompositeRegistration, ®)); } - if (!ret) {//Usually when a type name is "found" but invalid - //qDebug() << ret << urlString << QQmlMetaType::qmlType(url); + + // This means that the type couldn't be found by URL, but could not be + // registered either, meaning we most likely were passed some kind of bad + // data. + if (!ret) { if (!errors) // Cannot list errors properly, just quit qFatal("%s", QQmlMetaType::typeRegistrationFailures().join('\n').toLatin1().constData()); QQmlError error; @@ -704,7 +736,7 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader, if (candidate != end) { int major = vmajor ? *vmajor : -1; int minor = vminor ? *vminor : -1; - QQmlType *returnType = getTypeForUrl(componentUrl, type, isCompositeSingleton, 0, + QQmlType *returnType = fetchOrCreateTypeForUrl(componentUrl, type, isCompositeSingleton, 0, major, minor); if (type_return) *type_return = returnType; @@ -732,7 +764,7 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader, if (typeRecursionDetected) *typeRecursionDetected = true; } else { - QQmlType *returnType = getTypeForUrl(qmlUrl, type, false, 0); + QQmlType *returnType = fetchOrCreateTypeForUrl(qmlUrl, type, false, 0); if (type_return) *type_return = returnType; return returnType != 0; @@ -777,7 +809,7 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, return true; if (s->imports.count() == 1 && !s->imports.at(0)->isLibrary && type_return && s != &unqualifiedset) { // qualified, and only 1 url - *type_return = getTypeForUrl(resolveLocalUrl(s->imports.at(0)->url, unqualifiedtype.toString() + QLatin1String(".qml")), type, false, errors); + *type_return = fetchOrCreateTypeForUrl(resolveLocalUrl(s->imports.at(0)->url, unqualifiedtype.toString() + QLatin1String(".qml")), type, false, errors); return (*type_return != 0); } } -- cgit v1.2.3 From 0625b807030f26094db67b0265c9b40272814236 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 25 Jan 2017 19:54:33 +0100 Subject: QQmlImport: Add a little documentation for QQmlImportNamespace & Import Change-Id: Iee1dc32a5921b5da6d1511f26e93998baaae918e Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlimport.cpp | 46 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 659c7f1b9f..a12881aaf4 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -236,20 +236,49 @@ void qmlClearEnginePlugins() typedef QPair StaticPluginPair; #endif +/*! + \internal + + A QQmlImportNamespace is a way of seperating imports into a local namespace. + + Within a QML document, there is at least one namespace (the + "unqualified set") where imports without a qualifier are placed, i.e: + + import QtQuick 2.6 + + will have a single namespace (the unqualified set) containing a single import + for QtQuick 2.6. However, there may be others if an import statement gives + a qualifier, i.e the following will result in an additional new + QQmlImportNamespace in the qualified set: + + import MyFoo 1.0 as Foo +*/ class QQmlImportNamespace { public: QQmlImportNamespace() : nextNamespace(0) {} ~QQmlImportNamespace() { qDeleteAll(imports); } + /*! + \internal + + A QQmlImportNamespace::Import represents an actual instance of an import + within a namespace. + + \note The uri here may not necessarily be unique (e.g. for file imports). + + \note Version numbers may be -1 for file imports: this means that no + version was specified as part of the import. Type resolution will be + responsible for attempting to find the "best" possible version. + */ struct Import { - QString uri; - QString url; - int majversion; - int minversion; - bool isLibrary; - QQmlDirComponents qmlDirComponents; - QQmlDirScripts qmlDirScripts; + QString uri; // e.g. QtQuick + QString url; // the base path of the import + int majversion; // the major version imported + int minversion; // the minor version imported + bool isLibrary; // true means that this is not a file import + QQmlDirComponents qmlDirComponents; // a copy of the components listed in the qmldir + QQmlDirScripts qmlDirScripts; // a copy of the scripts in the qmldir bool setQmldirContent(const QString &resolvedUrl, const QQmlTypeLoader::QmldirContent *qmldir, QQmlImportNamespace *nameSpace, QList *errors); @@ -305,9 +334,12 @@ public: QString base; int ref; + // storage of data related to imports without a namespace mutable QQmlImportNamespace unqualifiedset; QQmlImportNamespace *findQualifiedNamespace(const QHashedStringRef &) const; + + // storage of data related to imports with a namespace mutable QFieldList qualifiedSets; QQmlTypeLoader *typeLoader; -- cgit v1.2.3 From 5f0eab2df3c82a71f70ea5a6535541fa786c6a78 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 25 Jan 2017 11:05:37 +0100 Subject: Slight improvements to resolveType for the common case Only resolveLocalUrl if we really have to. The string manipulation are quite expensive. This boosts tst_compilation::bigimport a tiny bit. Change-Id: I435633c8be9fcf4f8166900e8c0a52b320fb64d3 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlimport.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index a12881aaf4..bd41659f27 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -747,15 +747,17 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader, if ((candidate == end) || (c.majorVersion > candidate->majorVersion) || ((c.majorVersion == candidate->majorVersion) && (c.minorVersion > candidate->minorVersion))) { - componentUrl = resolveLocalUrl(QString(url + c.typeName + dotqml_string), c.fileName); - if (c.internal && base) { - if (resolveLocalUrl(*base, c.fileName) != componentUrl) - continue; // failed attempt to access an internal type - } - if (base && (*base == componentUrl)) { - if (typeRecursionDetected) - *typeRecursionDetected = true; - continue; // no recursion + if (base) { + componentUrl = resolveLocalUrl(QString(url + c.typeName + dotqml_string), c.fileName); + if (c.internal) { + if (resolveLocalUrl(*base, c.fileName) != componentUrl) + continue; // failed attempt to access an internal type + } + if (*base == componentUrl) { + if (typeRecursionDetected) + *typeRecursionDetected = true; + continue; // no recursion + } } // This is our best candidate so far @@ -766,6 +768,8 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader, } if (candidate != end) { + if (!base) // ensure we have a componentUrl + componentUrl = resolveLocalUrl(QString(url + candidate->typeName + dotqml_string), candidate->fileName); int major = vmajor ? *vmajor : -1; int minor = vminor ? *vminor : -1; QQmlType *returnType = fetchOrCreateTypeForUrl(componentUrl, type, isCompositeSingleton, 0, -- cgit v1.2.3