diff options
author | J-P Nurmi <jpnurmi@qt.io> | 2016-11-03 11:01:45 +0100 |
---|---|---|
committer | J-P Nurmi <jpnurmi@qt.io> | 2016-11-03 11:01:45 +0100 |
commit | da5083c11df4d9a6decd8d724098b6f108c4ab35 (patch) | |
tree | ee331004123ef2795025637c2905d9719f95f317 | |
parent | 462904396454ed0ee931c2a8f2b02c8a6508965a (diff) | |
parent | ef502bd71a0d81f1428263a11c38cd7c893ac515 (diff) |
Merge remote-tracking branch 'origin/5.8' into dev
Conflicts:
tools/qmljs/qmljs.cpp
Change-Id: Ifa9e74bdb780eaff22fbc9ba1c514d0078a3fb29
30 files changed, 276 insertions, 83 deletions
diff --git a/src/imports/imports.pro b/src/imports/imports.pro index affc1db2c0..cad02a2980 100644 --- a/src/imports/imports.pro +++ b/src/imports/imports.pro @@ -6,9 +6,10 @@ SUBDIRS += \ folderlistmodel \ localstorage \ models \ - settings \ statemachine +qtConfig(settings): SUBDIRS += settings + qtHaveModule(quick) { SUBDIRS += \ layouts \ diff --git a/src/imports/settings/settings.pro b/src/imports/settings/settings.pro index 3d7c9c31b8..29229f59cb 100644 --- a/src/imports/settings/settings.pro +++ b/src/imports/settings/settings.pro @@ -1,6 +1,3 @@ -load(qfeatures) -requires(!contains(QT_DISABLED_FEATURES, settings)) - CXX_MODULE = qml TARGET = qmlsettingsplugin TARGETPATH = Qt/labs/settings diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 11c8641e21..2467239be2 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -1,4 +1,4 @@ TEMPLATE = subdirs !contains(QT_CONFIG, no-qml-debug):SUBDIRS += qmltooling -SUBDIRS += scenegraph +qtHaveModule(quick):SUBDIRS += scenegraph diff --git a/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp index 31873f7915..b0f59717ac 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qdebugmessageservice.cpp @@ -70,7 +70,7 @@ void QDebugMessageServiceImpl::sendDebugMessage(QtMsgType type, //We just eavesdrop and forward the messages to a port //only if a client is connected to it. QQmlDebugPacket ws; - ws << QByteArray("MESSAGE") << type << buf.toUtf8(); + ws << QByteArray("MESSAGE") << int(type) << buf.toUtf8(); ws << QByteArray(ctxt.file) << ctxt.line << QByteArray(ctxt.function); ws << QByteArray(ctxt.category) << timer.nsecsElapsed(); diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp index a4320098c0..90e817e2fc 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp @@ -101,7 +101,7 @@ static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d, ds << static_cast<qint64>(d.locationId); messages.append(ds.squeezedData()); ds.clear(); - ds << d.time << QQmlProfilerDefinitions::RangeData + ds << d.time << int(QQmlProfilerDefinitions::RangeData) << static_cast<quint32>(d.detailType) << (i->location.sourceFile.isEmpty() ? i->url.toString() : i->location.sourceFile); diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp index eee1dd7eae..eae5e0a795 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp @@ -76,7 +76,7 @@ qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &m while (memoryData.length() > m_memoryPos && memoryData[m_memoryPos].timestamp <= until) { const QV4::Profiling::MemoryAllocationProperties &props = memoryData[m_memoryPos]; - d << props.timestamp << MemoryAllocation << props.type << props.size; + d << props.timestamp << int(MemoryAllocation) << int(props.type) << props.size; ++m_memoryPos; messages.append(d.squeezedData()); d.clear(); @@ -120,7 +120,7 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message return finalizeMessages(until, messages, m_stack.top(), d); appendMemoryEvents(m_stack.top(), messages, d); - d << m_stack.pop() << RangeEnd << Javascript; + d << m_stack.pop() << int(RangeEnd) << int(Javascript); messages.append(d.squeezedData()); d.clear(); } @@ -134,19 +134,19 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message appendMemoryEvents(props.start, messages, d); auto location = m_functionLocations.find(props.id); - d << props.start << RangeStart << Javascript; + d << props.start << int(RangeStart) << int(Javascript); if (trackLocations) d << static_cast<qint64>(props.id); if (location != m_functionLocations.end()) { messages.push_back(d.squeezedData()); d.clear(); - d << props.start << RangeLocation << Javascript << location->file << location->line + d << props.start << int(RangeLocation) << int(Javascript) << location->file << location->line << location->column; if (trackLocations) d << static_cast<qint64>(props.id); messages.push_back(d.squeezedData()); d.clear(); - d << props.start << RangeData << Javascript << location->name; + d << props.start << int(RangeData) << int(Javascript) << location->name; if (trackLocations) { d << static_cast<qint64>(props.id); diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 8f68131ced..90cbe04505 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -71,7 +71,7 @@ QT_BEGIN_NAMESPACE // Bump this whenever the compiler data structures change in an incompatible way. -#define QV4_DATA_STRUCTURE_VERSION 0x06 +#define QV4_DATA_STRUCTURE_VERSION 0x07 class QIODevice; class QQmlPropertyCache; @@ -587,7 +587,7 @@ struct Import ImportFile = 0x2, ImportScript = 0x3 }; - quint8 type; + LEUInt32 type; LEUInt32 uriIndex; LEUInt32 qualifierIndex; diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index b83bcdb83b..ca4e0b73d4 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -253,6 +253,7 @@ union Instr { enum Type { FOR_EACH_MOTH_INSTR(MOTH_INSTR_ENUM) + LastInstruction }; struct instr_common { diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index 5dd722bfc2..1f5c22eb97 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -1477,6 +1477,17 @@ bool CompilationUnit::saveCodeToDisk(QIODevice *device, const CompiledData::Unit QByteArray padding; +#ifdef MOTH_THREADED_INTERPRETER + // Map from instruction label back to instruction type. Only needed when persisting + // already linked compilation units; + QHash<void*, int> reverseInstructionMapping; + if (engine) { + void **instructions = VME::instructionJumpTable(); + for (int i = 0; i < Instr::LastInstruction; ++i) + reverseInstructionMapping.insert(instructions[i], i); + } +#endif + for (int i = 0; i < codeRefs.size(); ++i) { const CompiledData::Function *compiledFunction = unit->functionAt(i); @@ -1493,8 +1504,30 @@ bool CompilationUnit::saveCodeToDisk(QIODevice *device, const CompiledData::Unit return false; } - const void *codePtr = codeRefs.at(i).constData(); - written = device->write(reinterpret_cast<const char *>(codePtr), compiledFunction->codeSize); + QByteArray code = codeRefs.at(i); + +#ifdef MOTH_THREADED_INTERPRETER + if (!reverseInstructionMapping.isEmpty()) { + char *codePtr = code.data(); // detaches + int index = 0; + while (index < code.size()) { + Instr *genericInstr = reinterpret_cast<Instr *>(codePtr + index); + + genericInstr->common.instructionType = reverseInstructionMapping.value(genericInstr->common.code); + + switch (genericInstr->common.instructionType) { + #define REVERSE_INSTRUCTION(InstructionType, Member) \ + case Instr::InstructionType: \ + index += InstrMeta<(int)Instr::InstructionType>::Size; \ + break; + + FOR_EACH_MOTH_INSTR(REVERSE_INSTRUCTION) + } + } + } +#endif + + written = device->write(code.constData(), compiledFunction->codeSize); if (written != qint64(compiledFunction->codeSize)) { *errorString = device->errorString(); return false; diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp index a98cf6d338..4fa0cf421b 100644 --- a/src/qml/compiler/qv4ssa.cpp +++ b/src/qml/compiler/qv4ssa.cpp @@ -5077,6 +5077,10 @@ void mergeBasicBlocks(IR::Function *function, DefUses *du, DominatorTree *dt) BasicBlock *successor = bb->out.first(); if (successor->in.size() != 1) continue; // more than one incoming edge + // Loop header? No efficient way to update the other blocks that refer to this as containing group, + // so don't do merging yet. + if (successor->isGroupStart()) continue; + // Ok, we can merge the two basic blocks. if (DebugBlockMerging) { qDebug("Merging L%d into L%d", successor->index(), bb->index()); diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc index cc2fe90483..ac6600f38c 100644 --- a/src/qml/doc/src/cppintegration/data.qdoc +++ b/src/qml/doc/src/cppintegration/data.qdoc @@ -52,8 +52,8 @@ remain with C++ by invoking QQmlEngine::setObjectOwnership() with QQmlEngine::CppOwnership specified. Additionally, the QML engine respects the normal QObject parent ownership -semantics of Qt C++ objects, and will not ever take ownership of a QObject -instance which already has a parent. +semantics of Qt C++ objects, and will never delete a QObject instance which +has a parent. \section1 Basic Qt Data Types diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 4428c48d80..6d5cff4ecc 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -175,10 +175,7 @@ public: Q_ALWAYS_INLINE quint32 value() const { return _val & quint64(~quint32(0)); } Q_ALWAYS_INLINE quint32 tag() const { return _val >> 32; } -#if defined(V4_BOOTSTRAP) - Q_ALWAYS_INLINE Heap::Base *m() const { Q_UNREACHABLE(); return Q_NULLPTR; } - Q_ALWAYS_INLINE void setM(Heap::Base *b) { Q_UNUSED(b); Q_UNREACHABLE(); } -#elif defined(QV4_USE_64_BIT_VALUE_ENCODING) +#if defined(QV4_USE_64_BIT_VALUE_ENCODING) Q_ALWAYS_INLINE Heap::Base *m() const { Heap::Base *b; diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index b820777973..630d04938a 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -468,7 +468,7 @@ private: QQmlPropertyData *ensureResolved(QQmlPropertyData*) const; - void resolve(QQmlPropertyData *) const; + Q_NEVER_INLINE void resolve(QQmlPropertyData *) const; void updateRecur(const QMetaObject *); template<typename K> @@ -677,7 +677,7 @@ bool QQmlPropertyData::operator==(const QQmlPropertyRawData &other) inline QQmlPropertyData *QQmlPropertyCache::ensureResolved(QQmlPropertyData *p) const { - if (p && p->notFullyResolved()) + if (p && Q_UNLIKELY(p->notFullyResolved())) resolve(p); return p; diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp index 58eab508ad..03236ce2f7 100644 --- a/src/quick/accessible/qaccessiblequickitem.cpp +++ b/src/quick/accessible/qaccessiblequickitem.cpp @@ -67,10 +67,6 @@ int QAccessibleQuickItem::childCount() const QRect QAccessibleQuickItem::rect() const { const QRect r = itemScreenRect(item()); - - if (!r.isValid()) { - qWarning() << item()->metaObject()->className() << item()->property("accessibleText") << r; - } return r; } diff --git a/src/quick/doc/snippets/qml/localstorage/dbtransaction.js b/src/quick/doc/snippets/qml/localstorage/dbtransaction.js index 07d8a5618b..40eb6d2804 100644 --- a/src/quick/doc/snippets/qml/localstorage/dbtransaction.js +++ b/src/quick/doc/snippets/qml/localstorage/dbtransaction.js @@ -39,30 +39,47 @@ ****************************************************************************/ //![0] +var db = LocalStorage.openDatabaseSync("ActivityTrackDB", "", "Database tracking sports activities", 1000000); db.transaction( try { function(tx) { - tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]); + tx.executeSql('INSERT INTO trip_log VALUES(?, ?, ?)', + [ '01/10/2016','Sylling - Vikersund', '53' ]); } } catch (err) { - console.log("Error inserting into table Greeting"); + console.log("Error inserting into table Greeting: " + err); } ) //![0] //![1] +// Retrieve activity date, description and distance based on minimum +// distance parameter Pdistance +function db_distance_select(Pdistance) +{ +var db = LocalStorage.openDatabaseSync("ActivityTrackDB", "", "Database tracking sports activities", 1000000); db.transaction( function(tx) { - var results = tx.executeSql('SELECT salutation FROM Greeting WHERE salutee=?;', 'world'); + var results = tx.executeSql('SELECT rowid, + date, + trip_desc, + distance FROM trip_log + where distance >= ?',[Pdistance]'); + for (var i = 0; i < results.rows.length; i++) { + listModel.append({"id": results.rows.item(i).rowid, + "date": results.rows.item(i).date, + "trip_desc": results.rows.item(i).trip_desc, + "distance": results.rows.item(i).distance}); + } } - console.log("We greeted in this most respectful way: " + results.rows.item(0).value); -) +} //![1] //![2] -var db = LocalStorage.openDatabaseSync("QQmlExampleDB", "", "The Example QML SQL!", 1000000); +var db = LocalStorage.openDatabaseSync("ActivityTrackDB", "", "Database tracking sports activities", 1000000); if (db.version == '0.1') { db.changeVersion('0.1', '0.2', function(tx) { - tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]); + tx.executeSql('INSERT INTO trip_log VALUES(?, ?, ?)', + [ '01/10/2016','Sylling - Vikersund', '53' ]); } }); //![2] diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp index b943c28661..cbb052856e 100644 --- a/src/quick/items/qquickdrag.cpp +++ b/src/quick/items/qquickdrag.cpp @@ -749,7 +749,7 @@ void QQuickDragAttached::cancel() */ /*! - \qmlattachedsignal QtQuick::Drag::dragFinished(DropAction action) + \qmlattachedsignal QtQuick::Drag::dragFinished(DropAction dropAction) This signal is emitted when a drag finishes and the drag was started with the \l startDrag() method or started automatically using the \l dragType property. diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index fd872a5912..a05bb1617e 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -6303,7 +6303,7 @@ QPointF QQuickItem::position() const void QQuickItem::setX(qreal v) { Q_D(QQuickItem); - if (qIsNaN(v)) + if (qt_is_nan(v)) return; if (d->x == v) return; @@ -6320,7 +6320,7 @@ void QQuickItem::setX(qreal v) void QQuickItem::setY(qreal v) { Q_D(QQuickItem); - if (qIsNaN(v)) + if (qt_is_nan(v)) return; if (d->y == v) return; diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 9a43ee8bdf..16278ad744 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -2340,8 +2340,8 @@ QString QQuickTextInput::preeditText() const If true, the user can use the mouse to select text in some platform-specific way. Note that for some platforms this may - not be an appropriate interaction (eg. may conflict with how - the text needs to behave inside a Flickable. + not be an appropriate interaction (it may conflict with how + the text needs to behave inside a \l Flickable, for example). */ bool QQuickTextInput::selectByMouse() const { diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index f81c939ec6..dec5b44e2a 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1799,6 +1799,7 @@ bool QQuickWindowPrivate::deliverWheelEvent(QQuickItem *item, QWheelEvent *event if (item->contains(p)) { QWheelEvent wheel(p, p, event->pixelDelta(), event->angleDelta(), event->delta(), event->orientation(), event->buttons(), event->modifiers(), event->phase(), event->source(), event->inverted()); + wheel.setTimestamp(event->timestamp()); wheel.accept(); QCoreApplication::sendEvent(item, &wheel); if (wheel.isAccepted()) { diff --git a/src/quick/scenegraph/qsgcontextplugin.cpp b/src/quick/scenegraph/qsgcontextplugin.cpp index 3751891455..7fab9aeae8 100644 --- a/src/quick/scenegraph/qsgcontextplugin.cpp +++ b/src/quick/scenegraph/qsgcontextplugin.cpp @@ -148,9 +148,9 @@ QSGAdaptationBackendData *contextFactory() } } +#ifndef QT_NO_LIBRARY // Then try the plugins. if (!backendData->factory) { -#ifndef QT_NO_LIBRARY const int index = loader()->indexOf(requestedBackend); if (index != -1) backendData->factory = qobject_cast<QSGContextFactoryInterface*>(loader()->instance(index)); diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp index 3501f30487..b001899915 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp @@ -240,7 +240,8 @@ bool QSG24BitTextMaskShader::useSRGB() const // m_useSRGB is true, but if some QOGLFBO was bound check it's texture format: QOpenGLContext *ctx = QOpenGLContext::currentContext(); QOpenGLFramebufferObject *qfbo = QOpenGLContextPrivate::get(ctx)->qgl_current_fbo; - return !qfbo || qfbo->format().internalTextureFormat() == GL_SRGB8_ALPHA8_EXT; + bool fboInvalid = QOpenGLContextPrivate::get(ctx)->qgl_current_fbo_invalid; + return !qfbo || fboInvalid || qfbo->format().internalTextureFormat() == GL_SRGB8_ALPHA8_EXT; #else return m_useSRGB; #endif diff --git a/src/quick/util/qquickshortcut.cpp b/src/quick/util/qquickshortcut.cpp index 9725ddd671..3e04161639 100644 --- a/src/quick/util/qquickshortcut.cpp +++ b/src/quick/util/qquickshortcut.cpp @@ -41,10 +41,9 @@ #include <QtQuick/qquickitem.h> #include <QtQuick/qquickwindow.h> +#include <QtQuick/private/qtquickglobal_p.h> #include <QtGui/private/qguiapplication_p.h> -QT_BEGIN_NAMESPACE - /*! \qmltype Shortcut \instantiates QQuickShortcut @@ -89,6 +88,39 @@ QT_BEGIN_NAMESPACE The corresponding handler is \c onActivatedAmbiguously. */ +static bool qQuickShortcutContextMatcher(QObject *obj, Qt::ShortcutContext context) +{ + switch (context) { + case Qt::ApplicationShortcut: + return true; + case Qt::WindowShortcut: + while (obj && !obj->isWindowType()) { + obj = obj->parent(); + if (QQuickItem *item = qobject_cast<QQuickItem *>(obj)) + obj = item->window(); + } + return obj && obj == QGuiApplication::focusWindow(); + default: + return false; + } +} + +typedef bool (*ContextMatcher)(QObject *, Qt::ShortcutContext); + +Q_GLOBAL_STATIC_WITH_ARGS(ContextMatcher, ctxMatcher, (qQuickShortcutContextMatcher)) + +Q_QUICK_PRIVATE_EXPORT ContextMatcher qt_quick_shortcut_context_matcher() +{ + return *ctxMatcher(); +} + +Q_QUICK_PRIVATE_EXPORT void qt_quick_set_shortcut_context_matcher(ContextMatcher matcher) +{ + *ctxMatcher() = matcher; +} + +QT_BEGIN_NAMESPACE + QQuickShortcut::QQuickShortcut(QObject *parent) : QObject(parent), m_id(0), m_enabled(true), m_completed(false), m_autorepeat(true), m_context(Qt::WindowShortcut) { @@ -278,30 +310,13 @@ bool QQuickShortcut::event(QEvent *event) return false; } -static bool qQuickShortcutContextMatcher(QObject *obj, Qt::ShortcutContext context) -{ - switch (context) { - case Qt::ApplicationShortcut: - return true; - case Qt::WindowShortcut: - while (obj && !obj->isWindowType()) { - obj = obj->parent(); - if (QQuickItem *item = qobject_cast<QQuickItem *>(obj)) - obj = item->window(); - } - return obj && obj == QGuiApplication::focusWindow(); - default: - return false; - } -} - void QQuickShortcut::grabShortcut(const QKeySequence &sequence, Qt::ShortcutContext context) { ungrabShortcut(); if (m_completed && !sequence.isEmpty()) { QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance(); - m_id = pApp->shortcutMap.addShortcut(this, sequence, context, qQuickShortcutContextMatcher); + m_id = pApp->shortcutMap.addShortcut(this, sequence, context, *ctxMatcher()); if (!m_enabled) pApp->shortcutMap.setShortcutEnabled(false, m_id, this); if (!m_autorepeat) diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index 81018aa68e..2c7dde1b8d 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -194,6 +194,8 @@ private slots: void withNoContext(); void holeInPropertyData(); + void basicBlockMergeAfterLoopPeeling(); + signals: void testSignal(); }; @@ -4059,6 +4061,22 @@ void tst_QJSEngine::holeInPropertyData() QVERIFY(ok.toBool()); } +void tst_QJSEngine::basicBlockMergeAfterLoopPeeling() +{ + QJSEngine engine; + QJSValue ok = engine.evaluate( + "function crashMe() {\n" + " var seen = false;\n" + " while (globalVar) {\n" + " if (seen)\n" + " return;\n" + " seen = true;\n" + " }\n" + "}\n"); + QVERIFY(!ok.isCallable()); + +} + QTEST_MAIN(tst_QJSEngine) #include "tst_qjsengine.moc" diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp index 536bb40dcc..d0139b6cdf 100644 --- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp @@ -48,7 +48,7 @@ public: TestItem(QQuickItem *parent = 0) : QQuickItem(parent), focused(false), pressCount(0), releaseCount(0) , wheelCount(0), acceptIncomingTouchEvents(true) - , touchEventReached(false) {} + , touchEventReached(false), timestamp(0) {} bool focused; int pressCount; @@ -56,6 +56,7 @@ public: int wheelCount; bool acceptIncomingTouchEvents; bool touchEventReached; + ulong timestamp; protected: virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; } virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; } @@ -65,7 +66,7 @@ protected: touchEventReached = true; event->setAccepted(acceptIncomingTouchEvents); } - virtual void wheelEvent(QWheelEvent *event) { event->accept(); ++wheelCount; } + virtual void wheelEvent(QWheelEvent *event) { event->accept(); ++wheelCount; timestamp = event->timestamp(); } }; class TestWindow: public QQuickWindow @@ -1432,12 +1433,14 @@ void tst_qquickitem::wheelEvent() item->setVisible(visible); QWheelEvent event(QPoint(100, 50), -120, Qt::NoButton, Qt::NoModifier, Qt::Vertical); + event.setTimestamp(123456UL); event.setAccepted(false); QGuiApplication::sendEvent(&window, &event); if (shouldReceiveWheelEvents) { QVERIFY(event.isAccepted()); QCOMPARE(item->wheelCount, 1); + QCOMPARE(item->timestamp, 123456UL); } else { QVERIFY(!event.isAccepted()); QCOMPARE(item->wheelCount, 0); diff --git a/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp b/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp index 35a1aa8757..2df94bb84a 100644 --- a/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp +++ b/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp @@ -43,6 +43,8 @@ private slots: void sequence(); void context_data(); void context(); + void matcher_data(); + void matcher(); }; Q_DECLARE_METATYPE(Qt::Key) @@ -344,6 +346,68 @@ void tst_QQuickShortcut::context() || inactiveWindow->property("ambiguousShortcut").toString() == ambiguousShortcut); } +typedef bool (*ShortcutContextMatcher)(QObject *, Qt::ShortcutContext); +extern ShortcutContextMatcher qt_quick_shortcut_context_matcher(); +extern void qt_quick_set_shortcut_context_matcher(ShortcutContextMatcher matcher); + +static ShortcutContextMatcher lastMatcher = nullptr; + +static bool trueMatcher(QObject *, Qt::ShortcutContext) +{ + lastMatcher = trueMatcher; + return true; +} + +static bool falseMatcher(QObject *, Qt::ShortcutContext) +{ + lastMatcher = falseMatcher; + return false; +} + +Q_DECLARE_METATYPE(ShortcutContextMatcher) + +void tst_QQuickShortcut::matcher_data() +{ + QTest::addColumn<ShortcutContextMatcher>("matcher"); + QTest::addColumn<Qt::Key>("key"); + QTest::addColumn<QVariant>("shortcut"); + QTest::addColumn<QString>("activatedShortcut"); + + ShortcutContextMatcher tm = trueMatcher; + ShortcutContextMatcher fm = falseMatcher; + + QTest::newRow("F1") << tm << Qt::Key_F1 << shortcutMap("F1", Qt::ApplicationShortcut) << "F1"; + QTest::newRow("F2") << fm << Qt::Key_F2 << shortcutMap("F2", Qt::ApplicationShortcut) << ""; +} + +void tst_QQuickShortcut::matcher() +{ + QFETCH(ShortcutContextMatcher, matcher); + QFETCH(Qt::Key, key); + QFETCH(QVariant, shortcut); + QFETCH(QString, activatedShortcut); + + ShortcutContextMatcher defaultMatcher = qt_quick_shortcut_context_matcher(); + QVERIFY(defaultMatcher); + + qt_quick_set_shortcut_context_matcher(matcher); + QVERIFY(qt_quick_shortcut_context_matcher() == matcher); + + QQmlApplicationEngine engine(testFileUrl("shortcuts.qml")); + QQuickWindow *window = qobject_cast<QQuickWindow *>(engine.rootObjects().value(0)); + QVERIFY(window); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + window->setProperty("shortcuts", QVariantList() << shortcut); + QTest::keyClick(window, key); + + QVERIFY(lastMatcher == matcher); + QCOMPARE(window->property("activatedShortcut").toString(), activatedShortcut); + + qt_quick_set_shortcut_context_matcher(defaultMatcher); +} + QTEST_MAIN(tst_QQuickShortcut) #include "tst_qquickshortcut.moc" diff --git a/tests/auto/quick/qquicktext/BLACKLIST b/tests/auto/quick/qquicktext/BLACKLIST index f400af1d10..531d981159 100644 --- a/tests/auto/quick/qquicktext/BLACKLIST +++ b/tests/auto/quick/qquicktext/BLACKLIST @@ -1,7 +1,5 @@ [dependentImplicitSizes] * -[mouseSelection] -* [lineLaidOutRelayout] msvc-2015 [fontSizeMode] diff --git a/tests/auto/quick/qquicktextedit/BLACKLIST b/tests/auto/quick/qquicktextedit/BLACKLIST deleted file mode 100644 index 492d81531a..0000000000 --- a/tests/auto/quick/qquicktextedit/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[mouseSelection] -* diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp index 3c899c1e34..5ed0e9eea7 100644 --- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp @@ -2072,12 +2072,18 @@ void tst_qquicktextedit::mouseSelection() else if (clicks == 3) QTest::mouseDClick(&window, Qt::LeftButton, Qt::NoModifier, p1); QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p1); + if (clicks == 2) { + // QTBUG-50022: Since qtbase commit beef975, QTestLib avoids generating + // double click events by adding 500ms delta to release event timestamps. + // Send a double click event by hand to ensure the correct sequence: + // press, release, press, _dbl click_, move, release. + QMouseEvent dblClickEvent(QEvent::MouseButtonDblClick, p1, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + QGuiApplication::sendEvent(textEditObject, &dblClickEvent); + } QTest::mouseMove(&window, p2); QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, p2); QTRY_COMPARE(textEditObject->selectedText(), selectedText); - QTest::qWait(QGuiApplication::styleHints()->mouseDoubleClickInterval() + 10); - // Clicking and shift to clicking between the same points should select the same text. textEditObject->setCursorPosition(0); if (clicks > 1) @@ -2086,9 +2092,6 @@ void tst_qquicktextedit::mouseSelection() QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, p1); QTest::mouseClick(&window, Qt::LeftButton, Qt::ShiftModifier, p2); QTRY_COMPARE(textEditObject->selectedText(), selectedText); - - // ### This is to prevent double click detection from carrying over to the next test. - QTest::qWait(QGuiApplication::styleHints()->mouseDoubleClickInterval() + 10); } void tst_qquicktextedit::dragMouseSelection() @@ -3029,9 +3032,6 @@ void tst_qquicktextedit::middleClickPaste() // Middle click pastes the selected text, assuming the platform supports it. QTest::mouseClick(&window, Qt::MiddleButton, Qt::NoModifier, p3); - // ### This is to prevent double click detection from carrying over to the next test. - QTest::qWait(QGuiApplication::styleHints()->mouseDoubleClickInterval() + 10); - if (QGuiApplication::clipboard()->supportsSelection()) QCOMPARE(textEditObject->text().mid(1, selectedText.length()), selectedText); else diff --git a/tests/manual/scenegraph_lancelot/data/text/text_bitmapfont.qml b/tests/manual/scenegraph_lancelot/data/text/text_bitmapfont.qml new file mode 100644 index 0000000000..d1a289e24f --- /dev/null +++ b/tests/manual/scenegraph_lancelot/data/text/text_bitmapfont.qml @@ -0,0 +1,18 @@ +// test use of Fixedsys font on Windows + +import QtQuick 2.0 + +Item { + width: 320 + height: 480 + + Text { + anchors.fill: parent + wrapMode: Text.Wrap + font.family: "Fixedsys" + font.pixelSize: 20 + text: "Foobar" + } +} + + diff --git a/tools/qmljs/qmljs.cpp b/tools/qmljs/qmljs.cpp index 93276c1574..d09d2f7d0c 100644 --- a/tools/qmljs/qmljs.cpp +++ b/tools/qmljs/qmljs.cpp @@ -51,6 +51,8 @@ QT_REQUIRE_CONFIG(qml_interpreter); #include <QtCore/QCoreApplication> #include <QtCore/QFile> +#include <QtCore/QFileInfo> +#include <QtCore/QDateTime> #include <private/qqmljsengine_p.h> #include <private/qqmljslexer_p.h> #include <private/qqmljsparser_p.h> @@ -147,6 +149,7 @@ int main(int argc, char *argv[]) #endif bool runAsQml = false; + bool cache = false; if (!args.isEmpty()) { if (args.constFirst() == QLatin1String("--jit")) { @@ -166,6 +169,11 @@ int main(int argc, char *argv[]) args.removeFirst(); } + if (args.constFirst() == QLatin1String("--cache")) { + cache = true; + args.removeFirst(); + } + if (args.constFirst() == QLatin1String("--help")) { std::cerr << "Usage: qmljs [|--jit|--interpret|--qml] file..." << std::endl; return EXIT_SUCCESS; @@ -199,15 +207,38 @@ int main(int argc, char *argv[]) for (const QString &fn : qAsConst(args)) { QFile file(fn); if (file.open(QFile::ReadOnly)) { - const QString code = QString::fromUtf8(file.readAll()); - file.close(); + QScopedPointer<QV4::Script> script; + if (cache && QFile::exists(fn + QLatin1Char('c'))) { + QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = iSelFactory->createUnitForLoading(); + QString error; + if (unit->loadFromDisk(QUrl::fromLocalFile(fn), iSelFactory, &error)) { + script.reset(new QV4::Script(&vm, nullptr, unit)); + } else { + std::cout << "Error loading" << qPrintable(fn) << "from disk cache:" << qPrintable(error) << std::endl; + } + } + if (!script) { + const QString code = QString::fromUtf8(file.readAll()); + file.close(); + script.reset(new QV4::Script(ctx, code, fn)); + script->parseAsBinding = runAsQml; + script->parse(); + } QV4::ScopedValue result(scope); - QV4::Script script(ctx, code, fn); - script.parseAsBinding = runAsQml; - script.parse(); - if (!scope.engine->hasException) - result = script.run(); + if (!scope.engine->hasException) { + const auto unit = script->compilationUnit; + if (cache && unit && !(unit->data->flags & QV4::CompiledData::Unit::StaticData)) { + if (unit->data->sourceTimeStamp == 0) { + const_cast<QV4::CompiledData::Unit*>(unit->data)->sourceTimeStamp = QFileInfo(fn).lastModified().toMSecsSinceEpoch(); + } + QString saveError; + if (!unit->saveToDisk(QUrl::fromLocalFile(fn), &saveError)) { + std::cout << "Error saving JS cache file: " << qPrintable(saveError) << std::endl; + } + } + result = script->run(); + } if (scope.engine->hasException) { QV4::StackTrace trace; QV4::ScopedValue ex(scope, scope.engine->catchException(&trace)); |