diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2018-03-17 20:42:46 +0100 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2018-03-17 20:42:46 +0100 |
commit | 9477ba4e423276fe70e507ddbcc6e087def9f0ef (patch) | |
tree | 93034da8c847f030916d53d6fecbff21e4699457 | |
parent | 48e2b2e6eb37f06c93c77bde89e8ae0610038a6f (diff) | |
parent | 61447075954aab99b3abc9c78294e5966ae3b6ce (diff) |
Merge remote-tracking branch 'origin/5.11' into dev
Change-Id: I2e3ba907a6afcaa69354a894259c7b7accf3e3ac
40 files changed, 301 insertions, 131 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp index 5b049ab521..7950d21612 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp @@ -112,8 +112,14 @@ void JavaScriptJob::run() script.inheritContext = true; script.parse(); QV4::ScopedValue result(scope); - if (!scope.engine->hasException) - result = script.run(); + if (!scope.engine->hasException) { + if (frame) { + QV4::ScopedValue thisObject(scope, frame->thisObject()); + result = script.run(thisObject); + } else { + result = script.run(); + } + } if (scope.engine->hasException) { result = scope.engine->catchException(); resultIsException = true; diff --git a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp index 718975275a..e17fe92983 100644 --- a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp @@ -260,8 +260,14 @@ QV4::ReturnedValue NativeDebugger::evaluateExpression(const QString &expression) // That is a side-effect of inheritContext. script.inheritContext = true; script.parse(); - if (!m_engine->hasException) - return script.run(); + if (!m_engine->hasException) { + if (m_engine->currentStackFrame) { + QV4::ScopedValue thisObject(scope, m_engine->currentStackFrame->thisObject()); + script.run(thisObject); + } else { + script.run(); + } + } m_runningJob = false; return QV4::Encode::undefined(); diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 237cd9bf3b..a9d86b24f5 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -2213,12 +2213,6 @@ QV4::Compiler::Codegen::Reference JSCodeGen::fallbackNameLookup(const QString &n Reference imports = Reference::fromStackSlot(this, _importedScriptsSlot); return Reference::fromSubscript(imports, Reference::fromConst(this, QV4::Encode(r.scriptIndex))); } else if (r.type.isValid()) { - if (r.type.isCompositeSingleton()) { - Instruction::LoadQmlSingleton load; - load.name = registerString(name); - bytecodeGenerator->addInstruction(load); - return Reference::fromAccumulator(this); - } return Reference::fromName(this, name); } else { Q_ASSERT(r.importNamespace); diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 2c0320f7f1..f1776f5772 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -72,7 +72,7 @@ QT_BEGIN_NAMESPACE // Bump this whenever the compiler data structures change in an incompatible way. -#define QV4_DATA_STRUCTURE_VERSION 0x17 +#define QV4_DATA_STRUCTURE_VERSION 0x18 class QIODevice; class QQmlPropertyCache; diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index 34953d52ce..450fa50528 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -634,10 +634,6 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st MOTH_BEGIN_INSTR(LoadQmlImportedScripts) d << dumpRegister(result, nFormals); MOTH_END_INSTR(LoadQmlImportedScripts) - - MOTH_BEGIN_INSTR(LoadQmlSingleton) - d << name; - MOTH_END_INSTR(LoadQmlSingleton) } } diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 2d1428bd19..7dd639c94c 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -174,7 +174,6 @@ QT_BEGIN_NAMESPACE #define INSTR_Sub(op) INSTRUCTION(op, Sub, 1, lhs) #define INSTR_LoadQmlContext(op) INSTRUCTION(op, LoadQmlContext, 1, result) #define INSTR_LoadQmlImportedScripts(op) INSTRUCTION(op, LoadQmlImportedScripts, 1, result) -#define INSTR_LoadQmlSingleton(op) INSTRUCTION(op, LoadQmlSingleton, 1, name) #define FOR_EACH_MOTH_INSTR(F) \ @@ -290,9 +289,8 @@ QT_BEGIN_NAMESPACE F(Mod) \ F(Sub) \ F(LoadQmlContext) \ - F(LoadQmlImportedScripts) \ - F(LoadQmlSingleton) -#define MOTH_NUM_INSTRUCTIONS() (static_cast<int>(Moth::Instr::Type::LoadQmlSingleton) + 1) + F(LoadQmlImportedScripts) +#define MOTH_NUM_INSTRUCTIONS() (static_cast<int>(Moth::Instr::Type::LoadQmlImportedScripts) + 1) #if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) // icc before version 1200 doesn't support computed goto, and at least up to version 18.0.0 the diff --git a/src/qml/jit/qv4jit.cpp b/src/qml/jit/qv4jit.cpp index 5dc98a591a..bc46c0ca1d 100644 --- a/src/qml/jit/qv4jit.cpp +++ b/src/qml/jit/qv4jit.cpp @@ -917,14 +917,6 @@ void BaselineJIT::generate_LoadQmlImportedScripts(int result) as->storeReg(result); } -void BaselineJIT::generate_LoadQmlSingleton(int name) -{ - as->prepareCallWithArgCount(2); - as->passInt32AsArg(name, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlSingleton, Assembler::ResultInAccumulator); -} - void BaselineJIT::startInstruction(Instr::Type /*instr*/) { if (hasLabel()) @@ -1328,9 +1320,6 @@ void BaselineJIT::collectLabelsInBytecode() MOTH_BEGIN_INSTR(LoadQmlImportedScripts) MOTH_END_INSTR(LoadQmlImportedScripts) - - MOTH_BEGIN_INSTR(LoadQmlSingleton) - MOTH_END_INSTR(LoadQmlSingleton) } } #undef MOTH_BEGIN_INSTR diff --git a/src/qml/jit/qv4jit_p.h b/src/qml/jit/qv4jit_p.h index c17ab4ff6e..5aebf78a8d 100644 --- a/src/qml/jit/qv4jit_p.h +++ b/src/qml/jit/qv4jit_p.h @@ -240,7 +240,6 @@ public: void generate_Sub(int lhs) override; void generate_LoadQmlContext(int result) override; void generate_LoadQmlImportedScripts(int result) override; - void generate_LoadQmlSingleton(int name) override; void startInstruction(Moth::Instr::Type instr) override; void endInstruction(Moth::Instr::Type instr) override; diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index b697a2081b..82ce54224b 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -768,27 +768,6 @@ QObject *ExecutionEngine::qmlScopeObject() const return ctx->qml()->scopeObject; } -ReturnedValue ExecutionEngine::qmlSingletonWrapper(String *name) -{ - QQmlContextData *ctx = callingQmlContext(); - if (!ctx->imports) - return Encode::undefined(); - // Search for attached properties, enums and imported scripts - QQmlTypeNameCache::Result r = ctx->imports->query(name); - - Q_ASSERT(r.isValid()); - Q_ASSERT(r.type.isValid()); - Q_ASSERT(r.type.isSingleton()); - - QQmlType::SingletonInstanceInfo *siinfo = r.type.singletonInstanceInfo(); - QQmlEngine *e = qmlEngine(); - siinfo->init(e); - - if (QObject *qobjectSingleton = siinfo->qobjectApi(e)) - return QV4::QObjectWrapper::wrap(this, qobjectSingleton); - return QJSValuePrivate::convertedToValue(this, siinfo->scriptApi(e)); -} - QQmlContextData *ExecutionEngine::callingQmlContext() const { Heap::QmlContext *ctx = qmlContext(); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index d21b623a1e..3b515791a4 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -445,7 +445,6 @@ public: Heap::QmlContext *qmlContext() const; QObject *qmlScopeObject() const; - ReturnedValue qmlSingletonWrapper(String *name); QQmlContextData *callingQmlContext() const; diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index d99536829b..e10493b879 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -111,6 +111,8 @@ void Heap::RegExp::init(ExecutionEngine *engine, const QString &pattern, bool ig JSC::JSGlobalData dummy(internalClass->engine->regExpAllocator); JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, *jitCode); } +#else + Q_UNUSED(engine) #endif if (hasValidJITCode()) { valid = true; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 04cad8ddb7..2506777e76 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1326,13 +1326,6 @@ ReturnedValue Runtime::method_loadQmlImportedScripts(NoThrowEngine *engine) return context->importedScripts.value(); } -QV4::ReturnedValue Runtime::method_loadQmlSingleton(QV4::NoThrowEngine *engine, int nameIndex) -{ - Scope scope(engine); - ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]); - return engine->qmlSingletonWrapper(name); -} - ReturnedValue Runtime::method_uMinus(const Value &value) { TRACE1(value); diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h index 2956a4a463..91232256a9 100644 --- a/src/qml/jsruntime/qv4runtimeapi_p.h +++ b/src/qml/jsruntime/qv4runtimeapi_p.h @@ -184,7 +184,6 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> { /* qml */ \ F(ReturnedValue, loadQmlContext, (NoThrowEngine *engine)) \ F(ReturnedValue, loadQmlImportedScripts, (NoThrowEngine *engine)) \ - F(ReturnedValue, loadQmlSingleton, (NoThrowEngine *engine, int nameIndex)) \ F(ReturnedValue, loadQmlScopeObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired)) \ F(ReturnedValue, loadQmlContextObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired)) \ F(ReturnedValue, loadQmlIdObject, (ExecutionEngine *engine, const Value &context, uint index)) \ diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index bb6608bec0..267c93952d 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -136,7 +136,7 @@ void Script::parse() } } -ReturnedValue Script::run() +ReturnedValue Script::run(const QV4::Value *thisObject) { if (!parsed) parse(); @@ -149,10 +149,11 @@ ReturnedValue Script::run() if (qmlContext.isUndefined()) { TemporaryAssignment<Function*> savedGlobalCode(engine->globalCode, vmFunction); - return vmFunction->call(engine->globalObject, nullptr, 0, context); + return vmFunction->call(thisObject ? thisObject : engine->globalObject, nullptr, 0, + context); } else { Scoped<QmlContext> qml(valueScope, qmlContext.value()); - return vmFunction->call(nullptr, nullptr, 0, qml); + return vmFunction->call(thisObject, nullptr, 0, qml); } } diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h index 24291b9aa6..cb03c6b064 100644 --- a/src/qml/jsruntime/qv4script_p.h +++ b/src/qml/jsruntime/qv4script_p.h @@ -93,7 +93,7 @@ struct Q_QML_EXPORT Script { bool parseAsBinding; void parse(); - ReturnedValue run(); + ReturnedValue run(const QV4::Value *thisObject = nullptr); Function *function(); diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index feeeee527a..e73365e9b1 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -1369,10 +1369,6 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject, STACK_VALUE(result) = Runtime::method_loadQmlImportedScripts(static_cast<QV4::NoThrowEngine*>(engine)); MOTH_END_INSTR(LoadQmlImportedScripts) - MOTH_BEGIN_INSTR(LoadQmlSingleton) - acc = Runtime::method_loadQmlSingleton(static_cast<QV4::NoThrowEngine*>(engine), name); - MOTH_END_INSTR(LoadQmlSingleton) - catchException: Q_ASSERT(engine->hasException); if (!exceptionHandler) { diff --git a/src/qml/qml/ftw/qqmlthread.cpp b/src/qml/qml/ftw/qqmlthread.cpp index 78b477b472..96313d7627 100644 --- a/src/qml/qml/ftw/qqmlthread.cpp +++ b/src/qml/qml/ftw/qqmlthread.cpp @@ -57,6 +57,7 @@ public: void run() override; + inline QMutex &mutex() { return _mutex; } inline void lock() { _mutex.lock(); } inline void unlock() { _mutex.unlock(); } inline void wait() { _wait.wait(&_mutex); } @@ -263,6 +264,11 @@ bool QQmlThread::isShutdown() const return d->m_shutdown; } +QMutex &QQmlThread::mutex() +{ + return d->mutex(); +} + void QQmlThread::lock() { d->lock(); diff --git a/src/qml/qml/ftw/qqmlthread_p.h b/src/qml/qml/ftw/qqmlthread_p.h index 0ed12a2972..b5c580fe8b 100644 --- a/src/qml/qml/ftw/qqmlthread_p.h +++ b/src/qml/qml/ftw/qqmlthread_p.h @@ -59,6 +59,7 @@ QT_BEGIN_NAMESPACE class QThread; +class QMutex; class QQmlThreadPrivate; class QQmlThread @@ -71,6 +72,7 @@ public: void shutdown(); bool isShutdown() const; + QMutex &mutex(); void lock(); void unlock(); void wakeOne(); diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index 6e43bc735f..5dd3278b4c 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -593,6 +593,14 @@ void QQmlContextData::invalidate() parent = nullptr; } +void QQmlContextData::clearContextRecursively() +{ + clearContext(); + + for (auto ctxIt = childContexts; ctxIt; ctxIt = ctxIt->nextChild) + ctxIt->clearContextRecursively(); +} + void QQmlContextData::clearContext() { emitDestruction(); diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h index ff36d6c9a8..5dfee48848 100644 --- a/src/qml/qml/qqmlcontext_p.h +++ b/src/qml/qml/qqmlcontext_p.h @@ -115,6 +115,7 @@ public: QQmlContextData(QQmlContext *); void emitDestruction(); void clearContext(); + void clearContextRecursively(); void invalidate(); inline bool isValid() const { diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 61208d1c4a..5b954605e0 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -983,16 +983,6 @@ void QQmlTypeLoader::setProfiler(QQmlProfiler *profiler) } #endif -void QQmlTypeLoader::lock() -{ - m_thread->lock(); -} - -void QQmlTypeLoader::unlock() -{ - m_thread->unlock(); -} - struct PlainLoader { void loadThread(QQmlTypeLoader *loader, QQmlDataBlob *blob) const { @@ -1632,8 +1622,10 @@ bool QQmlTypeLoaderQmldirContent::designerSupported() const Constructs a new type loader that uses the given \a engine. */ QQmlTypeLoader::QQmlTypeLoader(QQmlEngine *engine) - : m_engine(engine), m_thread(new QQmlTypeLoaderThread(this)), - m_typeCacheTrimThreshold(TYPELOADER_MINIMUM_TRIM_THRESHOLD) + : m_engine(engine) + , m_thread(new QQmlTypeLoaderThread(this)) + , m_mutex(m_thread->mutex()) + , m_typeCacheTrimThreshold(TYPELOADER_MINIMUM_TRIM_THRESHOLD) { } diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 713f707387..df79d13f1c 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -313,8 +313,8 @@ public: bool isTypeLoaded(const QUrl &url) const; bool isScriptLoaded(const QUrl &url) const; - void lock(); - void unlock(); + void lock() { m_mutex.lock(); } + void unlock() { m_mutex.unlock(); } void load(QQmlDataBlob *, Mode = PreferSynchronous); void loadWithStaticData(QQmlDataBlob *, const QByteArray &, Mode = PreferSynchronous); @@ -381,6 +381,7 @@ private: QQmlEngine *m_engine; QQmlTypeLoaderThread *m_thread; + QMutex &m_mutex; #if QT_CONFIG(qml_debug) QScopedPointer<QQmlProfiler> m_profiler; diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp index c5d36297a4..d361efc79b 100644 --- a/src/quick/items/qquickanimatedsprite.cpp +++ b/src/quick/items/qquickanimatedsprite.cpp @@ -152,10 +152,10 @@ QT_BEGIN_NAMESPACE /*! \qmlproperty qreal QtQuick::AnimatedSprite::frameRate - Frames per second to show in the animation. Values equal to or below 0 are invalid. + Frames per second to show in the animation. Values less than or equal to \c 0 are invalid. - If frameRate is valid then it will be used to calculate the duration of the frames. - If not, and frameDuration is valid , then frameDuration will be used. + If \c frameRate is valid, it will be used to calculate the duration of the frames. + If not, and \l frameDuration is valid, \c frameDuration will be used. Changing this parameter will restart the animation. */ @@ -163,10 +163,10 @@ QT_BEGIN_NAMESPACE /*! \qmlproperty int QtQuick::AnimatedSprite::frameDuration - Duration of each frame of the animation in milliseconds. Values equal to or below 0 are invalid. + Duration of each frame of the animation in milliseconds. Values less than or equal to \c 0 are invalid. - If frameRate is valid then it will be used to calculate the duration of the frames. - If not, and frameDuration is valid, then frameDuration will be used. + If frameRate is valid, it will be used to calculate the duration of the frames. + If not, and \l frameDuration is valid, \c frameDuration will be used. Changing this parameter will restart the animation. */ @@ -218,21 +218,21 @@ QT_BEGIN_NAMESPACE /*! \qmlproperty bool QtQuick::AnimatedSprite::reverse - If true, then the animation will be played in reverse. + If \c true, the animation will be played in reverse. - Default is false. + Default is \c false. */ /*! \qmlproperty bool QtQuick::AnimatedSprite::frameSync - If true, then the animation will have no duration. Instead, the animation will advance + If \c true, the animation will have no duration. Instead, the animation will advance one frame each time a frame is rendered to the screen. This synchronizes it with the painting rate as opposed to elapsed time. If frameSync is set to true, it overrides both frameRate and frameDuration. - Default is false. + Default is \c false. Changing this parameter will restart the animation. */ @@ -242,9 +242,9 @@ QT_BEGIN_NAMESPACE After playing the animation this many times, the animation will automatically stop. Negative values are invalid. - If this is set to AnimatedSprite.Infinite the animation will not stop playing on its own. + If this is set to \c AnimatedSprite.Infinite the animation will not stop playing on its own. - Default is AnimatedSprite.Infinite + Default is \c AnimatedSprite.Infinite */ /*! @@ -252,13 +252,13 @@ QT_BEGIN_NAMESPACE When paused, the current frame can be advanced manually. - Default is false. + Default is \c false. */ /*! \qmlproperty int QtQuick::AnimatedSprite::currentFrame - When paused, the current frame can be advanced manually by setting this property or calling advance(). + When paused, the current frame can be advanced manually by setting this property or calling \l advance(). */ @@ -462,7 +462,7 @@ void QQuickAnimatedSprite::maybeUpdate() \qmlmethod int QtQuick::AnimatedSprite::pause() Pauses the sprite animation. This does nothing if - \l paused is true. + \l paused is \c true. \sa resume() */ @@ -481,7 +481,7 @@ void QQuickAnimatedSprite::pause() /*! \qmlmethod int QtQuick::AnimatedSprite::resume() - Resumes the sprite animation if \l paused is true; + Resumes the sprite animation if \l paused is \c true; otherwise, this does nothing. \sa pause() diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h index c4f0b60d92..2a1e9dc184 100644 --- a/src/quick/items/qquickevents_p_p.h +++ b/src/quick/items/qquickevents_p_p.h @@ -597,6 +597,7 @@ public: Area = QTouchDevice::Area, Pressure = QTouchDevice::Pressure, Velocity = QTouchDevice::Velocity, + MouseEmulation = QTouchDevice::MouseEmulation, // some bits reserved in case we need more of QTouchDevice::Capabilities Scroll = 0x0100, // mouse has a wheel, or there is OS-level scroll gesture recognition (dubious?) Hover = 0x0200, diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp index 34f30e81a3..6960e16bd9 100644 --- a/src/quick/items/qquickloader.cpp +++ b/src/quick/items/qquickloader.cpp @@ -102,7 +102,7 @@ void QQuickLoaderPrivate::clear() // this we may get transient errors from use of 'parent', for example. QQmlContext *context = qmlContext(object); if (context) - QQmlContextData::get(context)->invalidate(); + QQmlContextData::get(context)->clearContextRecursively(); if (loadingFromSource && component) { // disconnect since we deleteLater @@ -363,7 +363,7 @@ void QQuickLoader::setActive(bool newVal) // this we may get transient errors from use of 'parent', for example. QQmlContext *context = qmlContext(d->object); if (context) - QQmlContextData::get(context)->invalidate(); + QQmlContextData::get(context)->clearContextRecursively(); if (d->item) { QQuickItemPrivate *p = QQuickItemPrivate::get(d->item); diff --git a/src/quick/items/qquickspritesequence.cpp b/src/quick/items/qquickspritesequence.cpp index 0a39c09ebc..72761ab82b 100644 --- a/src/quick/items/qquickspritesequence.cpp +++ b/src/quick/items/qquickspritesequence.cpp @@ -73,38 +73,38 @@ QT_BEGIN_NAMESPACE Whether the sprite is animating or not. - Default is true + Default is \c true. */ /*! \qmlproperty bool QtQuick::SpriteSequence::interpolate - If true, interpolation will occur between sprite frames to make the + If \c true, interpolation will occur between sprite frames to make the animation appear smoother. - Default is true. + Default is \c true. */ /*! \qmlproperty string QtQuick::SpriteSequence::currentSprite - The name of the Sprite which is currently animating. + The name of the \l Sprite that is currently animating. */ /*! \qmlproperty string QtQuick::SpriteSequence::goalSprite - The name of the Sprite which the animation should move to. + The name of the \l Sprite that the animation should move to. - Sprite states have defined durations and transitions between them, setting goalState - will cause it to disregard any path weightings (including 0) and head down the path - which will reach the goalState quickest (fewest animations). It will pass through + Sprite states have defined durations and transitions between them; setting \c goalSprite + will cause it to disregard any path weightings (including \c 0) and head down the path + that will reach the \c goalSprite quickest (fewest animations). It will pass through intermediate states on that path, and animate them for their duration. - If it is possible to return to the goalState from the starting point of the goalState - it will continue to do so until goalState is set to "" or an unreachable state. + If it is possible to return to the \c goalSprite from the starting point of the \c goalSprite, + it will continue to do so until \c goalSprite is set to \c "" or an unreachable state. */ /*! \qmlmethod QtQuick::SpriteSequence::jumpTo(string sprite) - This function causes the SpriteSequence to jump to the specified sprite immediately, intermediate - sprites are not played. The \a sprite argument is the name of the sprite you wish to jump to. + This function causes the SpriteSequence to jump to the specified \a sprite immediately; + intermediate sprites are not played. */ /*! \qmlproperty list<Sprite> QtQuick::SpriteSequence::sprites diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index aefdaea2b7..48eba6a7a0 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -654,6 +654,12 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve Q_Q(QQuickWindow); auto device = pointerEvent->device(); + // A touch event from a trackpad is likely to be followed by a mouse or gesture event, so mouse event synth is redundant + if (device->type() == QQuickPointerDevice::TouchPad && device->capabilities().testFlag(QQuickPointerDevice::MouseEmulation)) { + qCDebug(DBG_TOUCH_TARGET) << "skipping delivery of synth-mouse event from" << device; + return false; + } + // FIXME: make this work for mouse events too and get rid of the asTouchEvent in here. Q_ASSERT(pointerEvent->asPointerTouchEvent()); QScopedPointer<QTouchEvent> event(pointerEvent->asPointerTouchEvent()->touchEventForItem(item)); @@ -2831,7 +2837,11 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event // In versions prior to Qt 6, we can't trust item->acceptTouchEvents() here, because it defaults to true. bool acceptsTouchEvents = false; #endif - if (acceptsTouchEvents || receiver->acceptedMouseButtons()) { + auto device = pte->device(); + if (device->type() == QQuickPointerDevice::TouchPad && + device->capabilities().testFlag(QQuickPointerDevice::MouseEmulation)) { + qCDebug(DBG_TOUCH_TARGET) << "skipping filtering of synth-mouse event from" << device; + } else if (acceptsTouchEvents || receiver->acceptedMouseButtons()) { // get a touch event customized for delivery to filteringParent QScopedPointer<QTouchEvent> filteringParentTouchEvent(pte->touchEventForItem(receiver, true)); if (filteringParentTouchEvent) { diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp index 1a13f6395a..2bb2af4fc0 100644 --- a/src/quick/util/qquickimageprovider.cpp +++ b/src/quick/util/qquickimageprovider.cpp @@ -680,15 +680,18 @@ QSize QQuickImageProviderWithOptions::loadSize(const QSize &originalSize, const return res; const bool preserveAspectCropOrFit = options.preserveAspectRatioCrop() || options.preserveAspectRatioFit(); + const bool formatIsSvg = (format == "svg" || format == "svgz"); - if (!preserveAspectCropOrFit && (format == "svg" || format == "svgz") && !requestedSize.isEmpty()) + if (!preserveAspectCropOrFit && formatIsSvg && !requestedSize.isEmpty()) return requestedSize; qreal ratio = 0.0; - if (requestedSize.width() && (preserveAspectCropOrFit || requestedSize.width() < originalSize.width())) { + if (requestedSize.width() && (preserveAspectCropOrFit || formatIsSvg || + requestedSize.width() < originalSize.width())) { ratio = qreal(requestedSize.width()) / originalSize.width(); } - if (requestedSize.height() && (preserveAspectCropOrFit || requestedSize.height() < originalSize.height())) { + if (requestedSize.height() && (preserveAspectCropOrFit || formatIsSvg || + requestedSize.height() < originalSize.height())) { qreal hr = qreal(requestedSize.height()) / originalSize.height(); if (ratio == 0.0) ratio = hr; diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp index 5dd62da15a..4ce0f9fd89 100644 --- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp +++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp @@ -316,6 +316,8 @@ private slots: void lastLineOfConditional_data(); void lastLineOfConditional(); + + void readThis(); private: QV4Debugger *debugger() const { @@ -865,6 +867,36 @@ void tst_qv4debugger::lastLineOfConditional() QCOMPARE(secondState.lineNumber, lastLine); } +void tst_qv4debugger::readThis() +{ + m_debuggerAgent->m_captureContextInfo = true; + QString script = + "var x = function() {\n" + " return this.a;\n" + "}.apply({a : 5}, []);\n"; + + TestAgent::ExpressionRequest request; + request.expression = "this"; + request.frameNr = 0; + request.context = -1; // no extra context + m_debuggerAgent->m_expressionRequests << request; + + debugger()->addBreakPoint("applyThis", 2); + evaluateJavaScript(script, "applyThis"); + QVERIFY(m_debuggerAgent->m_wasPaused); + + QCOMPARE(m_debuggerAgent->m_expressionResults.count(), 1); + QJsonObject result0 = m_debuggerAgent->m_expressionResults[0]; + QCOMPARE(result0.value("type").toString(), QStringLiteral("object")); + QCOMPARE(result0.value("value").toInt(), 1); + QJsonArray properties = result0.value("properties").toArray(); + QCOMPARE(properties.size(), 1); + QJsonObject a = properties.first().toObject(); + QCOMPARE(a.value("name").toString(), QStringLiteral("a")); + QCOMPARE(a.value("type").toString(), QStringLiteral("number")); + QCOMPARE(a.value("value").toInt(), 5); +} + void tst_qv4debugger::redundancy_data() { QTest::addColumn<bool>("redundantRefs"); diff --git a/tests/auto/qml/qqmlecmascript/data/signalHandlers.qml b/tests/auto/qml/qqmlecmascript/data/signalHandlers.qml index cd68fb9b82..14326bb9e6 100644 --- a/tests/auto/qml/qqmlecmascript/data/signalHandlers.qml +++ b/tests/auto/qml/qqmlecmascript/data/signalHandlers.qml @@ -102,4 +102,17 @@ QtObject { }) return testSuccess } + + property QtObject subObject: QtObject { + id: subObject + property int value + property bool ok: false + onValueChanged: this.ok = true + } + + function testThisInSignalHandler() { + subObject.ok = false + subObject.value = subObject.value + 1 + return subObject.ok + } } diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 5ff959515e..31cf40be16 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -6278,41 +6278,40 @@ void tst_qqmlecmascript::includeRemoteSuccess() void tst_qqmlecmascript::signalHandlers() { QQmlComponent component(&engine, testFileUrl("signalHandlers.qml")); - QObject *o = component.create(); + QScopedPointer<QObject> o(component.create()); QVERIFY(o != nullptr); - QCOMPARE(o->property("count").toInt(), 0); - QMetaObject::invokeMethod(o, "testSignalCall"); + QMetaObject::invokeMethod(o.data(), "testSignalCall"); QCOMPARE(o->property("count").toInt(), 1); - QMetaObject::invokeMethod(o, "testSignalHandlerCall"); + QMetaObject::invokeMethod(o.data(), "testSignalHandlerCall"); QCOMPARE(o->property("count").toInt(), 1); QCOMPARE(o->property("errorString").toString(), QLatin1String("TypeError: Property 'onTestSignal' of object [object Object] is not a function")); QCOMPARE(o->property("funcCount").toInt(), 0); - QMetaObject::invokeMethod(o, "testSignalConnection"); + QMetaObject::invokeMethod(o.data(), "testSignalConnection"); QCOMPARE(o->property("funcCount").toInt(), 1); - QMetaObject::invokeMethod(o, "testSignalHandlerConnection"); + QMetaObject::invokeMethod(o.data(), "testSignalHandlerConnection"); QCOMPARE(o->property("funcCount").toInt(), 2); - QMetaObject::invokeMethod(o, "testSignalDefined"); + QMetaObject::invokeMethod(o.data(), "testSignalDefined"); QCOMPARE(o->property("definedResult").toBool(), true); - QMetaObject::invokeMethod(o, "testSignalHandlerDefined"); + QMetaObject::invokeMethod(o.data(), "testSignalHandlerDefined"); QCOMPARE(o->property("definedHandlerResult").toBool(), true); QVariant result; - QMetaObject::invokeMethod(o, "testConnectionOnAlias", Q_RETURN_ARG(QVariant, result)); + QMetaObject::invokeMethod(o.data(), "testConnectionOnAlias", Q_RETURN_ARG(QVariant, result)); QCOMPARE(result.toBool(), true); - QMetaObject::invokeMethod(o, "testAliasSignalHandler", Q_RETURN_ARG(QVariant, result)); + QMetaObject::invokeMethod(o.data(), "testAliasSignalHandler", Q_RETURN_ARG(QVariant, result)); QCOMPARE(result.toBool(), true); - QMetaObject::invokeMethod(o, "testSignalWithClosureArgument", Q_RETURN_ARG(QVariant, result)); + QMetaObject::invokeMethod(o.data(), "testSignalWithClosureArgument", Q_RETURN_ARG(QVariant, result)); + QCOMPARE(result.toBool(), true); + QMetaObject::invokeMethod(o.data(), "testThisInSignalHandler", Q_RETURN_ARG(QVariant, result)); QCOMPARE(result.toBool(), true); - - delete o; } void tst_qqmlecmascript::qtbug_37351() diff --git a/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/SingletonType.qml b/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/SingletonType.qml index 7763c783f1..2913ceca08 100644 --- a/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/SingletonType.qml +++ b/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/SingletonType.qml @@ -2,4 +2,7 @@ import QtQuick 2.0 pragma Singleton Item { + enum EnumInSingleton { + EnumValue = 42 + } } diff --git a/tests/auto/qml/qqmllanguage/data/usingTypeWithEnum.qml b/tests/auto/qml/qqmllanguage/data/usingTypeWithEnum.qml index 2509fc0df1..43e54bbf1d 100644 --- a/tests/auto/qml/qqmllanguage/data/usingTypeWithEnum.qml +++ b/tests/auto/qml/qqmllanguage/data/usingTypeWithEnum.qml @@ -1,8 +1,10 @@ import QtQuick 2.0 +import org.qtproject.MixedModule 1.0 QtObject { property int enumValue: TypeWithEnum.EnumValue2 property int enumValue2: -1 property int scopedEnumValue: TypeWithEnum.MyEnum.EnumValue3 + property int enumValueFromSingleton: { var x = SingletonType.EnumValue; return x; } Component.onCompleted: enumValue2 = TypeWithEnum.EnumValue1 } diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 8bc631fbdd..f1f35f9fd4 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -3752,6 +3752,9 @@ void tst_qqmllanguage::scopedEnum() void tst_qqmllanguage::qmlEnums() { + QQmlEngine engine; + engine.setImportPathList(QStringList(defaultImportPathList) << testFile("lib")); + { QQmlComponent component(&engine, testFileUrl("TypeWithEnum.qml")); QScopedPointer<QObject> o(component.create()); @@ -3774,6 +3777,7 @@ void tst_qqmllanguage::qmlEnums() QCOMPARE(o->property("enumValue").toInt(), 1); QCOMPARE(o->property("enumValue2").toInt(), 0); QCOMPARE(o->property("scopedEnumValue").toInt(), 2); + QCOMPARE(o->property("enumValueFromSingleton").toInt(), 42); } } diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp index 3613ba6d87..d1f46a3912 100644 --- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp +++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp @@ -445,6 +445,12 @@ void tst_qquickimage::svg() // Due to aspect ratio calculations we can't get a precise // check for all setups, so we allow a small margin of error QVERIFY(qAbs(obj->height() - 141) < 1); + + // Setting it to a size bigger than the actual file, SVG formats + // can scale up although other image formats cannot + obj->setSourceSize(QSize(800,0)); + QCOMPARE(obj->width(), 800.0); + QVERIFY(qAbs(obj->height() - 1131) < 1); delete obj; } diff --git a/tests/auto/quick/qquickloader/data/rootContext.qml b/tests/auto/quick/qquickloader/data/rootContext.qml new file mode 100644 index 0000000000..277db43d57 --- /dev/null +++ b/tests/auto/quick/qquickloader/data/rootContext.qml @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests 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.0 + +Rectangle { + width: 360 + height: 360 + + property alias loader: loader + + Loader { + id: loader + } + + property Component component: Item { + property bool trigger: false + onTriggerChanged: { + objectInRootContext.doIt() // make sure we can resolve objectInRootContext + loader.active = false + objectInRootContext.doIt() // make sure we can STILL resolve objectInRootContext + anotherProperty = true // see if we can trigger subsequent signal handlers (we shouldn't) + } + property bool anotherProperty: false + onAnotherPropertyChanged: { + // this should never be executed + objectInRootContext.doIt() + } + } +} diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp index 30fc52f95a..7a176661e8 100644 --- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp +++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp @@ -29,6 +29,7 @@ #include <QSignalSpy> +#include <QtQml/QQmlContext> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> #include <QtQml/qqmlincubator.h> @@ -123,6 +124,8 @@ private slots: void bindings(); void parentErrors(); + + void rootContext(); }; Q_DECLARE_METATYPE(QList<QQmlError>) @@ -1327,6 +1330,64 @@ void tst_QQuickLoader::parentErrors() QVERIFY2(warningsSpy.isEmpty(), qPrintable(failureMessage)); } +class ObjectInRootContext: public QObject +{ + Q_OBJECT + +public: + int didIt = 0; + +public slots: + void doIt() { + didIt += 1; + } +}; + +void tst_QQuickLoader::rootContext() +{ + QQmlEngine engine; + ObjectInRootContext objectInRootContext; + engine.rootContext()->setContextProperty("objectInRootContext", &objectInRootContext); + + QQmlComponent component(&engine, testFileUrl("rootContext.qml")); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + + QQuickLoader *loader = object->property("loader").value<QQuickLoader*>(); + QVERIFY(loader); + + QSignalSpy warningsSpy(&engine, SIGNAL(warnings(QList<QQmlError>))); + + // Give the loader a component + loader->setSourceComponent(object->property("component").value<QQmlComponent*>()); + QTRY_VERIFY(loader->active()); + QTRY_VERIFY(loader->item()); + + QString failureMessage; + if (!warningsSpy.isEmpty()) { + QDebug stream(&failureMessage); + stream << warningsSpy.first().first().value<QList<QQmlError>>(); + } + QVERIFY2(warningsSpy.isEmpty(), qPrintable(failureMessage)); + QCOMPARE(objectInRootContext.didIt, 0); + + // Deactivate the loader, which deletes the item. + // Check that a) there are no errors, and b) the objectInRootContext can still be resolved even + // after deactivating the loader. If it cannot, a ReferenceError for objectInRootContext is + // generated (and the 'doIt' counter in objectInRootContext will be 1 for the call before + // the deactivation). + loader->item()->setProperty("trigger", true); + QTRY_VERIFY(!loader->active()); + QTRY_VERIFY(!loader->item()); + + if (!warningsSpy.isEmpty()) { + QDebug stream(&failureMessage); + stream << warningsSpy.first().first().value<QList<QQmlError>>(); + } + QVERIFY2(warningsSpy.isEmpty(), qPrintable(failureMessage)); + QCOMPARE(objectInRootContext.didIt, 2); +} + QTEST_MAIN(tst_QQuickLoader) #include "tst_qquickloader.moc" diff --git a/tests/manual/imagehandler/embeddedimage.svg b/tests/manual/imagehandler/embeddedimage.svg new file mode 100644 index 0000000000..f952640822 --- /dev/null +++ b/tests/manual/imagehandler/embeddedimage.svg @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.2" baseProfile="tiny"> + + <desc>This document has a reference to an external image</desc> + + <image x="200" y="200" width="100" height="100" xlink:href="heart.png"> + <title>External image</title> + </image> +</svg> diff --git a/tests/manual/imagehandler/heart.png b/tests/manual/imagehandler/heart.png Binary files differnew file mode 100644 index 0000000000..deaec18274 --- /dev/null +++ b/tests/manual/imagehandler/heart.png diff --git a/tests/manual/imagehandler/main.qml b/tests/manual/imagehandler/main.qml index 55e5b89cae..ec474e62ce 100644 --- a/tests/manual/imagehandler/main.qml +++ b/tests/manual/imagehandler/main.qml @@ -41,6 +41,10 @@ Window { width: parent.width sourceSize.height: height sourceSize.width: width + MouseArea { + anchors.fill: parent + onClicked: svgImage.source = "embeddedimage.svg" + } } ListModel { id: imageFillModeModel @@ -57,7 +61,7 @@ Window { height: 75 anchors.bottom: parent.bottom Text { - text: "Click the options below to change the fill mode" + text: "Click the options below to change the fill mode.<br>Click the image to change the used image." font.pointSize: 16 } |