aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-03-17 20:42:46 +0100
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-03-17 20:42:46 +0100
commit9477ba4e423276fe70e507ddbcc6e087def9f0ef (patch)
tree93034da8c847f030916d53d6fecbff21e4699457
parent48e2b2e6eb37f06c93c77bde89e8ae0610038a6f (diff)
parent61447075954aab99b3abc9c78294e5966ae3b6ce (diff)
Merge remote-tracking branch 'origin/5.11' into dev
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp10
-rw-r--r--src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp10
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp6
-rw-r--r--src/qml/compiler/qv4compileddata_p.h2
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp4
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h6
-rw-r--r--src/qml/jit/qv4jit.cpp11
-rw-r--r--src/qml/jit/qv4jit_p.h1
-rw-r--r--src/qml/jsruntime/qv4engine.cpp21
-rw-r--r--src/qml/jsruntime/qv4engine_p.h1
-rw-r--r--src/qml/jsruntime/qv4regexp.cpp2
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp7
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h1
-rw-r--r--src/qml/jsruntime/qv4script.cpp7
-rw-r--r--src/qml/jsruntime/qv4script_p.h2
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp4
-rw-r--r--src/qml/qml/ftw/qqmlthread.cpp6
-rw-r--r--src/qml/qml/ftw/qqmlthread_p.h2
-rw-r--r--src/qml/qml/qqmlcontext.cpp8
-rw-r--r--src/qml/qml/qqmlcontext_p.h1
-rw-r--r--src/qml/qml/qqmltypeloader.cpp16
-rw-r--r--src/qml/qml/qqmltypeloader_p.h5
-rw-r--r--src/quick/items/qquickanimatedsprite.cpp32
-rw-r--r--src/quick/items/qquickevents_p_p.h1
-rw-r--r--src/quick/items/qquickloader.cpp4
-rw-r--r--src/quick/items/qquickspritesequence.cpp24
-rw-r--r--src/quick/items/qquickwindow.cpp12
-rw-r--r--src/quick/util/qquickimageprovider.cpp9
-rw-r--r--tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp32
-rw-r--r--tests/auto/qml/qqmlecmascript/data/signalHandlers.qml13
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp25
-rw-r--r--tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/SingletonType.qml3
-rw-r--r--tests/auto/qml/qqmllanguage/data/usingTypeWithEnum.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp4
-rw-r--r--tests/auto/quick/qquickimage/tst_qquickimage.cpp6
-rw-r--r--tests/auto/quick/qquickloader/data/rootContext.qml55
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp61
-rw-r--r--tests/manual/imagehandler/embeddedimage.svg10
-rw-r--r--tests/manual/imagehandler/heart.pngbin0 -> 15194 bytes
-rw-r--r--tests/manual/imagehandler/main.qml6
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
new file mode 100644
index 0000000000..deaec18274
--- /dev/null
+++ b/tests/manual/imagehandler/heart.png
Binary files differ
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
}