aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/masm/assembler/LinkBuffer.h13
-rw-r--r--src/3rdparty/masm/stubs/ExecutableAllocator.h1
-rw-r--r--src/3rdparty/masm/yarr/YarrJIT.cpp40
-rw-r--r--src/3rdparty/masm/yarr/YarrJIT.h25
-rw-r--r--src/imports/localstorage/plugin.cpp27
-rw-r--r--src/imports/testlib/TestCase.qml69
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp2
-rw-r--r--src/qml/compiler/qv4codegen.cpp3
-rw-r--r--src/qml/configure.json9
-rw-r--r--src/qml/doc/src/cppintegration/data.qdoc3
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc52
-rw-r--r--src/qml/jit/qv4assemblercommon.cpp44
-rw-r--r--src/qml/jsruntime/jsruntime.pri20
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4engine.cpp31
-rw-r--r--src/qml/jsruntime/qv4executableallocator.cpp10
-rw-r--r--src/qml/jsruntime/qv4executableallocator_p.h1
-rw-r--r--src/qml/jsruntime/qv4function.cpp17
-rw-r--r--src/qml/jsruntime/qv4function_p.h5
-rw-r--r--src/qml/jsruntime/qv4functiontable_noop.cpp65
-rw-r--r--src/qml/jsruntime/qv4functiontable_p.h75
-rw-r--r--src/qml/jsruntime/qv4functiontable_unix.cpp99
-rw-r--r--src/qml/jsruntime/qv4functiontable_win64.cpp153
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp13
-rw-r--r--src/qml/parser/parser.pri3
-rw-r--r--src/qml/parser/qqmljsastfwd_p.h22
-rw-r--r--src/qml/parser/qqmljsengine_p.h4
-rw-r--r--src/qml/parser/qqmljssourcelocation_p.h87
-rw-r--r--src/qml/qml.pro1
-rw-r--r--src/qml/qml/qml.pri4
-rw-r--r--src/qml/qml/qqmlabstracturlinterceptor.h4
-rw-r--r--src/qml/qml/qqmlbinding.cpp2
-rw-r--r--src/qml/qml/qqmlengine_p.h2
-rw-r--r--src/qml/qml/qqmlexpression.cpp1
-rw-r--r--src/qml/qml/qqmlextensioninterface.h4
-rw-r--r--src/qml/qml/qqmlglobal_p.h10
-rw-r--r--src/qml/qml/qqmlmetatype.cpp7
-rw-r--r--src/qml/qml/qqmlmetatype_p.h2
-rw-r--r--src/qml/qml/qqmltypeloader.cpp2
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp5
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h1
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp12
-rw-r--r--src/qml/qmldirparser/qmldirparser.pri11
-rw-r--r--src/qml/qmldirparser/qqmldirparser.cpp (renamed from src/qml/qml/qqmldirparser.cpp)2
-rw-r--r--src/qml/qmldirparser/qqmldirparser_p.h (renamed from src/qml/qml/qqmldirparser_p.h)4
-rw-r--r--src/qml/qmldirparser/qqmlerror.cpp (renamed from src/qml/qml/qqmlerror.cpp)16
-rw-r--r--src/qml/qmldirparser/qqmlerror.h (renamed from src/qml/qml/qqmlerror.h)4
-rw-r--r--src/qml/qmldirparser/qqmlsourcecoordinate_p.h72
-rw-r--r--src/qmldebug/qmldebug.pro13
-rw-r--r--src/qmldebug/qqmlenginedebugclient.cpp566
-rw-r--r--src/qmldebug/qqmlenginedebugclient_p.h168
-rw-r--r--src/qmldebug/qqmlenginedebugclient_p_p.h76
-rw-r--r--src/qmldebug/qqmlinspectorclient.cpp150
-rw-r--r--src/qmldebug/qqmlinspectorclient_p.h74
-rw-r--r--src/qmldebug/qqmlinspectorclient_p_p.h69
-rw-r--r--src/qmldebug/qv4debugclient.cpp578
-rw-r--r--src/qmldebug/qv4debugclient_p.h121
-rw-r--r--src/qmldebug/qv4debugclient_p_p.h80
-rw-r--r--src/qmldevtools/qmldevtools.pro1
-rw-r--r--src/qmltest/qmltest.pro2
-rw-r--r--src/qmltest/quicktest.cpp97
-rw-r--r--src/qmltest/quicktest.h13
-rw-r--r--src/qmltest/quicktestresult.cpp16
-rw-r--r--src/qmltest/quicktestresult_p.h3
-rw-r--r--src/quick/accessible/qaccessiblequickview.cpp2
-rw-r--r--src/quick/designer/qquickdesignersupportitems.cpp10
-rw-r--r--src/quick/handlers/handlers.pri1
-rw-r--r--src/quick/handlers/qquicksinglepointhandler.cpp62
-rw-r--r--src/quick/handlers/qquicksinglepointhandler_p.h16
-rw-r--r--src/quick/handlers/qquicksinglepointhandler_p_p.h79
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp2
-rw-r--r--src/quick/items/qquickflickable_p.h2
-rw-r--r--src/quick/items/qquickitem.cpp2
-rw-r--r--src/quick/items/qquickitemviewfxitem.cpp2
-rw-r--r--src/quick/items/qquickitemviewfxitem_p_p.h8
-rw-r--r--src/quick/items/qquickopenglshadereffect.cpp17
-rw-r--r--src/quick/items/qquicktableview.cpp10
-rw-r--r--src/quick/items/qquicktableview_p.h9
-rw-r--r--src/quick/items/qquicktextnodeengine.cpp2
-rw-r--r--src/quick/items/qquickwindow.cpp56
-rw-r--r--src/quick/items/qquickwindowmodule.cpp6
-rw-r--r--src/quick/quick.pro1
-rw-r--r--src/quick/scenegraph/util/qsgimagenode.h2
-rw-r--r--src/quick/scenegraph/util/qsgninepatchnode.h2
-rw-r--r--src/quick/scenegraph/util/qsgrectanglenode.h2
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp79
-rw-r--r--src/quick/util/qquickpixmapcache.cpp3
87 files changed, 3155 insertions, 312 deletions
diff --git a/src/3rdparty/masm/assembler/LinkBuffer.h b/src/3rdparty/masm/assembler/LinkBuffer.h
index c79b0663c8..4dfd051797 100644
--- a/src/3rdparty/masm/assembler/LinkBuffer.h
+++ b/src/3rdparty/masm/assembler/LinkBuffer.h
@@ -228,6 +228,8 @@ public:
return m_size;
}
+ inline void makeExecutable();
+
private:
template <typename T> T applyOffset(T src)
{
@@ -353,6 +355,11 @@ inline void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::performF
ASSERT(m_size <= INT_MAX);
MacroAssembler::cacheFlush(code(), m_size);
+}
+
+template <typename MacroAssembler, template <typename T> class ExecutableOffsetCalculator>
+inline void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::makeExecutable()
+{
ExecutableAllocator::makeExecutable(code(), static_cast<int>(m_size));
}
@@ -389,6 +396,7 @@ public:
}
inline void performFinalization();
+ inline void makeExecutable();
inline void linkCode(void* ownerUID, JITCompilationEffort);
@@ -421,6 +429,11 @@ inline void BranchCompactingLinkBuffer<MacroAssembler>::performFinalization()
#endif
MacroAssembler::cacheFlush(code(), m_size);
+}
+
+template <typename MacroAssembler>
+inline void BranchCompactingLinkBuffer<MacroAssembler>::makeExecutable()
+{
ExecutableAllocator::makeExecutable(code(), m_initialSize);
}
diff --git a/src/3rdparty/masm/stubs/ExecutableAllocator.h b/src/3rdparty/masm/stubs/ExecutableAllocator.h
index 156b24b4e8..a439c53827 100644
--- a/src/3rdparty/masm/stubs/ExecutableAllocator.h
+++ b/src/3rdparty/masm/stubs/ExecutableAllocator.h
@@ -82,6 +82,7 @@ struct ExecutableMemoryHandle : public RefCounted<ExecutableMemoryHandle> {
inline bool isManaged() const { return true; }
+ void *exceptionHandler() { return m_allocation->exceptionHandler(); }
void *start() { return m_allocation->start(); }
size_t sizeInBytes() { return m_size; }
diff --git a/src/3rdparty/masm/yarr/YarrJIT.cpp b/src/3rdparty/masm/yarr/YarrJIT.cpp
index 9a9ab581e8..73c919dd90 100644
--- a/src/3rdparty/masm/yarr/YarrJIT.cpp
+++ b/src/3rdparty/masm/yarr/YarrJIT.cpp
@@ -33,6 +33,8 @@
#include "Yarr.h"
#include "YarrCanonicalize.h"
+#include <private/qv4functiontable_p.h>
+
#if ENABLE(YARR_JIT)
using namespace WTF;
@@ -3529,17 +3531,30 @@ public:
m_backtrackingState.linkDataLabels(linkBuffer);
+ CodeRef codeRef;
if (compileMode == MatchOnly) {
- if (m_charSize == Char8)
- codeBlock.set8BitCodeMatchOnly(FINALIZE_CODE(linkBuffer, "YarJIT", "Match-only 8-bit regular expression"));
- else
- codeBlock.set16BitCodeMatchOnly(FINALIZE_CODE(linkBuffer, "YarJIT", "Match-only 16-bit regular expression"));
+ if (m_charSize == Char8) {
+ codeRef = FINALIZE_CODE(linkBuffer, "YarJIT",
+ "Match-only 8-bit regular expression");
+ codeBlock.set8BitCodeMatchOnly(codeRef);
+ } else {
+ codeRef = FINALIZE_CODE(linkBuffer, "YarJIT",
+ "Match-only 16-bit regular expression");
+ codeBlock.set16BitCodeMatchOnly(codeRef);
+ }
} else {
- if (m_charSize == Char8)
- codeBlock.set8BitCode(FINALIZE_CODE(linkBuffer, "YarJIT", "8-bit regular expression"));
- else
- codeBlock.set16BitCode(FINALIZE_CODE(linkBuffer, "YarJIT", "16-bit regular expression"));
+ if (m_charSize == Char8) {
+ codeRef = FINALIZE_CODE(linkBuffer, "YarJIT", "8-bit regular expression");
+ codeBlock.set8BitCode(codeRef);
+ } else {
+ codeRef = FINALIZE_CODE(linkBuffer, "YarJIT", "16-bit regular expression");
+ codeBlock.set16BitCode(codeRef);
+ }
}
+ QV4::generateFunctionTable(nullptr, &codeRef);
+
+ linkBuffer.makeExecutable();
+
if (m_failureReason)
codeBlock.setFallBackWithFailureReason(*m_failureReason);
}
@@ -3587,6 +3602,15 @@ private:
BacktrackingState m_backtrackingState;
};
+void YarrCodeBlock::replaceCodeRef(MacroAssemblerCodeRef &target,
+ const MacroAssemblerCodeRef &source)
+{
+ if (!!target && target.code().executableAddress() != source.code().executableAddress())
+ QV4::destroyFunctionTable(nullptr, &target);
+
+ target = source;
+}
+
static void dumpCompileFailure(JITFailureReason failure)
{
switch (failure) {
diff --git a/src/3rdparty/masm/yarr/YarrJIT.h b/src/3rdparty/masm/yarr/YarrJIT.h
index 8b6b3a7577..35a0690f6e 100644
--- a/src/3rdparty/masm/yarr/YarrJIT.h
+++ b/src/3rdparty/masm/yarr/YarrJIT.h
@@ -82,19 +82,28 @@ class YarrCodeBlock {
public:
YarrCodeBlock() = default;
+ ~YarrCodeBlock() { clear(); }
+
+ static void replaceCodeRef(MacroAssemblerCodeRef &target, const MacroAssemblerCodeRef &source);
void setFallBackWithFailureReason(JITFailureReason failureReason) { m_failureReason = failureReason; }
std::optional<JITFailureReason> failureReason() { return m_failureReason; }
bool has8BitCode() { return m_ref8.size(); }
bool has16BitCode() { return m_ref16.size(); }
- void set8BitCode(MacroAssemblerCodeRef ref) { m_ref8 = ref; }
- void set16BitCode(MacroAssemblerCodeRef ref) { m_ref16 = ref; }
+ void set8BitCode(MacroAssemblerCodeRef ref) { replaceCodeRef(m_ref8, ref); }
+ void set16BitCode(MacroAssemblerCodeRef ref) { replaceCodeRef(m_ref16, ref); }
bool has8BitCodeMatchOnly() { return m_matchOnly8.size(); }
bool has16BitCodeMatchOnly() { return m_matchOnly16.size(); }
- void set8BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly8 = matchOnly; }
- void set16BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly16 = matchOnly; }
+ void set8BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly)
+ {
+ replaceCodeRef(m_matchOnly8, matchOnly);
+ }
+ void set16BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly)
+ {
+ replaceCodeRef(m_matchOnly16, matchOnly);
+ }
#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
bool usesPatternContextBuffer() { return m_usesPatternContextBuffer; }
@@ -190,10 +199,10 @@ public:
void clear()
{
- m_ref8 = MacroAssemblerCodeRef();
- m_ref16 = MacroAssemblerCodeRef();
- m_matchOnly8 = MacroAssemblerCodeRef();
- m_matchOnly16 = MacroAssemblerCodeRef();
+ replaceCodeRef(m_ref8, MacroAssemblerCodeRef());
+ replaceCodeRef(m_ref16, MacroAssemblerCodeRef());
+ replaceCodeRef(m_matchOnly8, MacroAssemblerCodeRef());
+ replaceCodeRef(m_matchOnly16, MacroAssemblerCodeRef());
m_failureReason = std::nullopt;
}
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index e7e8d130bb..3c34d8e45a 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -399,23 +399,23 @@ static ReturnedValue qmlsqldatabase_changeVersion(const FunctionObject *b, const
if (from_version != *r->d()->version)
V4THROW_SQL(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(*r->d()->version));
- Scoped<QQmlSqlDatabaseWrapper> w(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
- ScopedObject p(scope, databaseData(scope.engine)->queryProto.value());
- w->setPrototypeUnchecked(p.getPointer());
- w->d()->type = Heap::QQmlSqlDatabaseWrapper::Query;
- *w->d()->database = db;
- *w->d()->version = *r->d()->version;
-
bool ok = true;
if (!!callback) {
+ Scoped<QQmlSqlDatabaseWrapper> query(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
+ ScopedObject p(scope, databaseData(scope.engine)->queryProto.value());
+ query->setPrototypeUnchecked(p.getPointer());
+ query->d()->type = Heap::QQmlSqlDatabaseWrapper::Query;
+ *query->d()->database = db;
+ *query->d()->version = *r->d()->version;
+
ok = false;
db.transaction();
JSCallData jsCall(scope, 1);
*jsCall->thisObject = scope.engine->globalObject;
- jsCall->args[0] = w;
+ jsCall->args[0] = query;
- TransactionRollback rollbackOnException(&db, &w->d()->inTransaction);
+ TransactionRollback rollbackOnException(&db, &query->d()->inTransaction);
callback->call(jsCall);
rollbackOnException.clear();
if (!db.commit()) {
@@ -427,12 +427,18 @@ static ReturnedValue qmlsqldatabase_changeVersion(const FunctionObject *b, const
}
if (ok) {
+ Scoped<QQmlSqlDatabaseWrapper> w(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
+ ScopedObject p(scope, databaseData(scope.engine)->databaseProto.value());
+ w->setPrototypeUnchecked(p.getPointer());
+ w->d()->type = Heap::QQmlSqlDatabaseWrapper::Database;
+ *w->d()->database = db;
*w->d()->version = to_version;
#if QT_CONFIG(settings)
const QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(scope.engine->qmlEngine());
QSettings ini(enginePrivate->offlineStorageDatabaseDirectory() + db.connectionName() + QLatin1String(".ini"), QSettings::IniFormat);
ini.setValue(QLatin1String("Version"), to_version);
#endif
+ RETURN_RESULT(w.asReturnedValue());
}
RETURN_UNDEFINED();
@@ -599,7 +605,8 @@ This data can be used by application tools.
\section3 db.changeVersion(from, to, callback(tx))
-This method allows you to perform a \e{Scheme Upgrade}.
+This method allows you to perform a \e{Scheme Upgrade}. If it succeeds it returns a new
+database object of version \e to. Otherwise it returns \e undefined.
If the current version of \e db is not \e from, then an exception is thrown.
diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml
index 266e3111bb..fd61c042ca 100644
--- a/src/imports/testlib/TestCase.qml
+++ b/src/imports/testlib/TestCase.qml
@@ -521,6 +521,75 @@ Item {
}
/*!
+ \since 5.13
+ \qmlmethod bool TestCase::isPolishScheduled(object item)
+
+ Returns \c true if \l {QQuickItem::}{updatePolish()} has not been called
+ on \a item since the last call to \l {QQuickItem::}{polish()},
+ otherwise returns \c false.
+
+ When assigning values to properties in QML, any layouting the item
+ must do as a result of the assignment might not take effect immediately,
+ but can instead be postponed until the item is polished. For these cases,
+ you can use this function to ensure that the item has been polished
+ before the execution of the test continues. For example:
+
+ \code
+ verify(isPolishScheduled(item))
+ verify(waitForItemPolished(item))
+ \endcode
+
+ Without the call to \c isPolishScheduled() above, the
+ call to \c waitForItemPolished() might see that no polish
+ was scheduled and therefore pass instantly, assuming that
+ the item had already been polished. This function
+ makes it obvious why an item wasn't polished and allows tests to
+ fail early under such circumstances.
+
+ \sa waitForItemPolished(), QQuickItem::polish(), QQuickItem::updatePolish()
+ */
+ function isPolishScheduled(item) {
+ if (!item || typeof item !== "object") {
+ qtest_results.fail("Argument must be a valid Item; actual type is " + typeof item,
+ util.callerFile(), util.callerLine())
+ throw new Error("QtQuickTest::fail")
+ }
+
+ return qtest_results.isPolishScheduled(item)
+ }
+
+ /*!
+ \since 5.13
+ \qmlmethod bool waitForItemPolished(object item, int timeout = 5000)
+
+ Waits for \a timeout milliseconds or until
+ \l {QQuickItem::}{updatePolish()} has been called on \a item.
+
+ Returns \c true if \c updatePolish() was called on \a item within
+ \a timeout milliseconds, otherwise returns \c false.
+
+ \sa isPolishScheduled(), QQuickItem::polish(), QQuickItem::updatePolish()
+ */
+ function waitForItemPolished(item, timeout) {
+ if (!item || typeof item !== "object") {
+ qtest_results.fail("First argument must be a valid Item; actual type is " + typeof item,
+ util.callerFile(), util.callerLine())
+ throw new Error("QtQuickTest::fail")
+ }
+
+ if (timeout !== undefined && typeof(timeout) != "number") {
+ qtest_results.fail("Second argument must be a number; actual type is " + typeof timeout,
+ util.callerFile(), util.callerLine())
+ throw new Error("QtQuickTest::fail")
+ }
+
+ if (!timeout)
+ timeout = 5000
+
+ return qtest_results.waitForItemPolished(item, timeout)
+ }
+
+ /*!
\since 5.9
\qmlmethod object TestCase::createTemporaryQmlObject(string qml, object parent, string filePath)
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 2421e8c1ea..84fd66b114 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -2510,8 +2510,6 @@ QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedO
f->location = compiledFunction->location;
f->nameIndex = compiledFunction->nameIndex;
- const QString name = unit->stringAtInternal(compiledFunction->nameIndex);
-
f->formals.allocate(pool, int(compiledFunction->nFormals));
const quint32_le *formalNameIdx = compiledFunction->formalsTable();
for (uint i = 0; i < compiledFunction->nFormals; ++i, ++formalNameIdx)
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index f570af4819..cdba21604d 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -2563,9 +2563,6 @@ bool Codegen::visit(ObjectPattern *ast)
TailCallBlocker blockTailCalls(this);
- QVector<QPair<Reference, ObjectPropertyValue>> computedProperties;
- QMap<QString, ObjectPropertyValue> valueMap;
-
RegisterScope scope(this);
QStringList members;
diff --git a/src/qml/configure.json b/src/qml/configure.json
index 878ec0119b..c7b145f46f 100644
--- a/src/qml/configure.json
+++ b/src/qml/configure.json
@@ -8,6 +8,7 @@
"commandline": {
"options": {
"qml-network": "boolean",
+ "qml-tracing": "boolean",
"qml-debug": "boolean"
}
},
@@ -38,6 +39,13 @@
"condition": "features.network",
"output": [ "publicFeature" ]
},
+ "qml-tracing": {
+ "label": "QML tracing JIT support",
+ "purpose": "Provides a JIT that uses trace information generated by the interpreter.",
+ "section": "QML",
+ "output": [ "publicFeature" ],
+ "autoDetect": false
+ },
"qml-debug": {
"label": "QML debugging and profiling support",
"purpose": "Provides infrastructure and plugins for debugging and profiling.",
@@ -131,6 +139,7 @@
"entries": [
"qml-network",
"qml-debug",
+ "qml-tracing",
"qml-sequence-object",
"qml-list-model",
"qml-xml-http-request",
diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc
index 8ebbd28737..171b2b6a11 100644
--- a/src/qml/doc/src/cppintegration/data.qdoc
+++ b/src/qml/doc/src/cppintegration/data.qdoc
@@ -284,6 +284,9 @@ In particular, QML currently supports:
\li \c {std::vector<bool>}
\endlist
+and all registered QList, QVector, QQueue, QStack, QSet, QLinkedList, std::list,
+std::vector that contain a type marked with \l Q_DECLARE_METATYPE.
+
These sequence types are implemented directly in terms of the underlying C++
sequence. There are two ways in which such sequences can be exposed to QML:
as a Q_PROPERTY of the given sequence type; or as the return type of a
diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
index 2bb1fcac61..15e8e4c52c 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
@@ -540,6 +540,58 @@ Internally, however, the rectangle can correctly set its \c color
property and refer to the actual defined property rather than the alias.
+\section4 Property Aliases and Types
+
+Property aliases cannot have explicit type specifications. The type of a
+property alias is the \e declared type of the property or object it refers to.
+Therefore, if you create an alias to an object referenced via id with extra
+properties declared inline, the extra properties won't be accessible through
+the alias:
+
+\code
+// MyItem.qml
+Item {
+ property alias inner: innerItem
+
+ Item {
+ id: innerItem
+ property int extraProperty
+ }
+}
+\code
+
+You cannot initialize \a inner.extraProperty from outside of this component, as
+inner is only an \a Item:
+
+\code
+// main.qml
+MyItem {
+ inner.extraProperty: 5 // fails
+}
+\code
+
+However, if you extract the inner object into a separate component with a
+dedicated .qml file, you can instantiate that component instead and have all
+its properties available through the alias:
+
+\code
+// MainItem.qml
+Item {
+ // Now you can access inner.extraProperty, as inner is now an ExtraItem
+ property alias inner: innerItem
+
+ ExtraItem {
+ id: innerItem
+ }
+}
+
+// ExtraItem.qml
+Item {
+ property int extraProperty
+}
+\code
+
+
\section3 Default Properties
An object definition can have a single \e default property. A default property
diff --git a/src/qml/jit/qv4assemblercommon.cpp b/src/qml/jit/qv4assemblercommon.cpp
index b302ac6403..bc17be229d 100644
--- a/src/qml/jit/qv4assemblercommon.cpp
+++ b/src/qml/jit/qv4assemblercommon.cpp
@@ -43,6 +43,7 @@
#include "qv4engine_p.h"
#include "qv4assemblercommon_p.h"
#include <private/qv4function_p.h>
+#include <private/qv4functiontable_p.h>
#include <private/qv4runtime_p.h>
#include <assembler/MacroAssemblerCodeRef.h>
@@ -112,17 +113,6 @@ static void printDisassembledOutputWithCalls(QByteArray processedOutput,
qDebug("%s", processedOutput.constData());
}
-static QByteArray functionName(Function *function)
-{
- QByteArray name = function->name()->toQString().toUtf8();
- if (name.isEmpty()) {
- name = QByteArray::number(reinterpret_cast<quintptr>(function), 16);
- name.prepend("QV4::Function(0x");
- name.append(')');
- }
- return name;
-}
-
JIT::PlatformAssemblerCommon::~PlatformAssemblerCommon()
{}
@@ -147,7 +137,9 @@ void PlatformAssemblerCommon::link(Function *function, const char *jitKind)
buf.open(QIODevice::WriteOnly);
WTF::setDataFile(new QIODevicePrintStream(&buf));
- QByteArray name = functionName(function);
+ // We use debugAddress here because it's actually for debugging and hidden behind an
+ // environment variable.
+ const QByteArray name = Function::prettyName(function, linkBuffer.debugAddress()).toUtf8();
codeRef = linkBuffer.finalizeCodeWithDisassembly(jitKind, "function %s", name.constData());
WTF::setDataFile(stderr);
@@ -159,31 +151,9 @@ void PlatformAssemblerCommon::link(Function *function, const char *jitKind)
function->codeRef = new JSC::MacroAssemblerCodeRef(codeRef);
function->jittedCode = reinterpret_cast<Function::JittedCode>(function->codeRef->code().executableAddress());
- // This implements writing of JIT'd addresses so that perf can find the
- // symbol names.
- //
- // Perf expects the mapping to be in a certain place and have certain
- // content, for more information, see:
- // https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/jit-interface.txt
- static bool doProfile = !qEnvironmentVariableIsEmpty("QV4_PROFILE_WRITE_PERF_MAP");
- if (Q_UNLIKELY(doProfile)) {
- static QFile perfMapFile(QString::fromLatin1("/tmp/perf-%1.map")
- .arg(QCoreApplication::applicationPid()));
- static const bool isOpen = perfMapFile.open(QIODevice::WriteOnly);
- if (!isOpen) {
- qWarning("QV4::JIT::Assembler: Cannot write perf map file.");
- doProfile = false;
- } else {
- perfMapFile.write(QByteArray::number(reinterpret_cast<quintptr>(
- codeRef.code().executableAddress()), 16));
- perfMapFile.putChar(' ');
- perfMapFile.write(QByteArray::number(static_cast<qsizetype>(codeRef.size()), 16));
- perfMapFile.putChar(' ');
- perfMapFile.write(functionName(function));
- perfMapFile.putChar('\n');
- perfMapFile.flush();
- }
- }
+ generateFunctionTable(function, &codeRef);
+
+ linkBuffer.makeExecutable();
}
void PlatformAssemblerCommon::prepareCallWithArgCount(int argc)
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index 5ec55b960b..a24ee0a188 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -147,7 +147,8 @@ HEADERS += \
$$PWD/qv4value_p.h \
$$PWD/qv4string_p.h \
$$PWD/qv4util_p.h \
- $$PWD/qv4value_p.h
+ $$PWD/qv4value_p.h \
+ $$PWD/qv4functiontable_p.h
SOURCES += \
$$PWD/qv4engine.cpp \
@@ -156,6 +157,23 @@ SOURCES += \
$$PWD/qv4value.cpp \
$$PWD/qv4executableallocator.cpp
+qmldevtools_build {
+ SOURCES += \
+ $$PWD/qv4functiontable_noop.cpp
+} else:win32 {
+ !winrt:equals(QT_ARCH, x86_64) {
+ SOURCES += \
+ $$PWD/qv4functiontable_win64.cpp
+ } else {
+ SOURCES += \
+ $$PWD/qv4functiontable_noop.cpp
+ }
+} else {
+ SOURCES += \
+ $$PWD/qv4functiontable_unix.cpp
+}
+
+
valgrind {
DEFINES += V4_USE_VALGRIND
}
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index a13fb37a52..21c6a5d06b 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -670,17 +670,17 @@ static inline QString ToTimeString(double t)
static inline QString ToLocaleString(double t)
{
- return ToDateTime(t, Qt::LocalTime).toString(Qt::LocaleDate);
+ return ToDateTime(t, Qt::LocalTime).toString(Qt::DefaultLocaleShortDate);
}
static inline QString ToLocaleDateString(double t)
{
- return ToDateTime(t, Qt::LocalTime).date().toString(Qt::LocaleDate);
+ return ToDateTime(t, Qt::LocalTime).date().toString(Qt::DefaultLocaleShortDate);
}
static inline QString ToLocaleTimeString(double t)
{
- return ToDateTime(t, Qt::LocalTime).time().toString(Qt::LocaleDate);
+ return ToDateTime(t, Qt::LocalTime).time().toString(Qt::DefaultLocaleShortDate);
}
static double getLocalTZA()
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 57a364b205..ff7bcb63fa 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -1597,6 +1597,22 @@ static QV4::ReturnedValue variantListToJS(QV4::ExecutionEngine *v4, const QVaria
return a.asReturnedValue();
}
+// Converts a QSequentialIterable to JS.
+// The result is a new Array object with length equal to the length
+// of the QSequentialIterable, and the elements being the QSequentialIterable's
+// elements converted to JS, recursively.
+static QV4::ReturnedValue sequentialIterableToJS(QV4::ExecutionEngine *v4, const QSequentialIterable &lst)
+{
+ QV4::Scope scope(v4);
+ QV4::ScopedArrayObject a(scope, v4->newArrayObject());
+ a->arrayReserve(lst.size());
+ QV4::ScopedValue v(scope);
+ for (int i = 0; i < lst.size(); i++)
+ a->arrayPut(i, (v = variantToJS(v4, lst.at(i))));
+ a->setArrayLengthUnchecked(lst.size());
+ return a.asReturnedValue();
+}
+
// Converts a QVariantMap to JS.
// The result is a new Object object with property names being
// the keys of the QVariantMap, and values being the values of
@@ -1701,9 +1717,18 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data)
return QV4::Encode::null();
}
QMetaType mt(type);
- if (mt.flags() & QMetaType::IsGadget) {
- Q_ASSERT(mt.metaObject());
- return QV4::QQmlValueTypeWrapper::create(this, QVariant(type, data), mt.metaObject(), type);
+ if (auto metaObject = mt.metaObject()) {
+ auto flags = mt.flags();
+ if (flags & QMetaType::IsGadget) {
+ return QV4::QQmlValueTypeWrapper::create(this, QVariant(type, data), metaObject, type);
+ } else if (flags & QMetaType::PointerToQObject) {
+ return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(data));
+ }
+ }
+ if (QMetaType::hasRegisteredConverterFunction(type, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) {
+ auto v = QVariant(type, data);
+ QSequentialIterable lst = v.value<QSequentialIterable>();
+ return sequentialIterableToJS(this, lst);
}
// Fall back to wrapping in a QVariant.
return QV4::Encode(newVariantObject(QVariant(type, data)));
diff --git a/src/qml/jsruntime/qv4executableallocator.cpp b/src/qml/jsruntime/qv4executableallocator.cpp
index 6f04a712e6..c836d121e3 100644
--- a/src/qml/jsruntime/qv4executableallocator.cpp
+++ b/src/qml/jsruntime/qv4executableallocator.cpp
@@ -38,17 +38,23 @@
****************************************************************************/
#include "qv4executableallocator_p.h"
+#include "qv4functiontable_p.h"
#include <wtf/StdLibExtras.h>
#include <wtf/PageAllocation.h>
using namespace QV4;
-void *ExecutableAllocator::Allocation::start() const
+void *ExecutableAllocator::Allocation::exceptionHandler() const
{
return reinterpret_cast<void*>(addr);
}
+void *ExecutableAllocator::Allocation::start() const
+{
+ return reinterpret_cast<void*>(addr + exceptionHandlerSize());
+}
+
void ExecutableAllocator::Allocation::deallocate(ExecutableAllocator *allocator)
{
if (isValid())
@@ -162,7 +168,7 @@ ExecutableAllocator::Allocation *ExecutableAllocator::allocate(size_t size)
Allocation *allocation = nullptr;
// Code is best aligned to 16-byte boundaries.
- size = WTF::roundUpToMultipleOf(16, size);
+ size = WTF::roundUpToMultipleOf(16, size + exceptionHandlerSize());
QMultiMap<size_t, Allocation*>::Iterator it = freeAllocations.lowerBound(size);
if (it != freeAllocations.end()) {
diff --git a/src/qml/jsruntime/qv4executableallocator_p.h b/src/qml/jsruntime/qv4executableallocator_p.h
index 375c9a365f..013c6d7120 100644
--- a/src/qml/jsruntime/qv4executableallocator_p.h
+++ b/src/qml/jsruntime/qv4executableallocator_p.h
@@ -86,6 +86,7 @@ public:
, free(true)
{}
+ void *exceptionHandler() const;
void *start() const;
void invalidate() { addr = 0; }
bool isValid() const { return addr != 0; }
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 941c37de5b..2a82d96f1d 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -46,6 +46,7 @@
#include "qv4lookup_p.h"
#include <private/qv4mm_p.h>
#include <private/qv4identifiertable_p.h>
+#include <private/qv4functiontable_p.h>
#include <assembler/MacroAssemblerCodeRef.h>
#include <private/qv4vme_moth_p.h>
#include <private/qqmlglobal_p.h>
@@ -98,7 +99,10 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit,
Function::~Function()
{
- delete codeRef;
+ if (codeRef) {
+ destroyFunctionTable(this, codeRef);
+ delete codeRef;
+ }
}
void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArray> &parameters)
@@ -145,6 +149,17 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr
nFormals = parameters.size();
}
+QString Function::prettyName(const Function *function, const void *code)
+{
+ QString prettyName = function ? function->name()->toQString() : QString();
+ if (prettyName.isEmpty()) {
+ prettyName = QString::number(reinterpret_cast<quintptr>(code), 16);
+ prettyName.prepend(QLatin1String("QV4::Function(0x"));
+ prettyName.append(QLatin1Char(')'));
+ }
+ return prettyName;
+}
+
QQmlSourceLocation Function::sourceLocation() const
{
return QQmlSourceLocation(sourceFile(), compiledFunction->location.line, compiledFunction->location.column);
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 029dd7786b..86343ea061 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -89,9 +89,12 @@ struct Q_QML_EXPORT Function {
// used when dynamically assigning signal handlers (QQmlConnection)
void updateInternalClass(ExecutionEngine *engine, const QList<QByteArray> &parameters);
- inline Heap::String *name() {
+ inline Heap::String *name() const {
return compilationUnit->runtimeStrings[compiledFunction->nameIndex];
}
+
+ static QString prettyName(const Function *function, const void *address);
+
inline QString sourceFile() const { return compilationUnit->fileName(); }
inline QUrl finalUrl() const { return compilationUnit->finalUrl(); }
diff --git a/src/qml/jsruntime/qv4functiontable_noop.cpp b/src/qml/jsruntime/qv4functiontable_noop.cpp
new file mode 100644
index 0000000000..31c198eb00
--- /dev/null
+++ b/src/qml/jsruntime/qv4functiontable_noop.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4functiontable_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+void generateFunctionTable(Function *function, JSC::MacroAssemblerCodeRef *codeRef)
+{
+ Q_UNUSED(function);
+ Q_UNUSED(codeRef);
+}
+
+void destroyFunctionTable(Function *function, JSC::MacroAssemblerCodeRef *codeRef)
+{
+ Q_UNUSED(function);
+ Q_UNUSED(codeRef);
+}
+
+size_t exceptionHandlerSize()
+{
+ return 0;
+}
+
+} // QV4
+
+QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4functiontable_p.h b/src/qml/jsruntime/qv4functiontable_p.h
new file mode 100644
index 0000000000..69e3d2bdd5
--- /dev/null
+++ b/src/qml/jsruntime/qv4functiontable_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4FUNCTIONTABLE_P_H
+#define QV4FUNCTIONTABLE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qv4global_p.h"
+
+namespace JSC {
+class MacroAssemblerCodeRef;
+}
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+struct Function;
+
+void generateFunctionTable(Function *function, JSC::MacroAssemblerCodeRef *codeRef);
+void destroyFunctionTable(Function *function, JSC::MacroAssemblerCodeRef *codeRef);
+
+size_t exceptionHandlerSize();
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QV4FUNCTIONTABLE_P_H
diff --git a/src/qml/jsruntime/qv4functiontable_unix.cpp b/src/qml/jsruntime/qv4functiontable_unix.cpp
new file mode 100644
index 0000000000..25b5c27161
--- /dev/null
+++ b/src/qml/jsruntime/qv4functiontable_unix.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4functiontable_p.h"
+#include "qv4function_p.h"
+
+#include <assembler/MacroAssemblerCodeRef.h>
+
+#include <QtCore/qfile.h>
+#include <QtCore/qcoreapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+void generateFunctionTable(Function *function, JSC::MacroAssemblerCodeRef *codeRef)
+{
+ // This implements writing of JIT'd addresses so that perf can find the
+ // symbol names.
+ //
+ // Perf expects the mapping to be in a certain place and have certain
+ // content, for more information, see:
+ // https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/jit-interface.txt
+ static bool doProfile = !qEnvironmentVariableIsEmpty("QV4_PROFILE_WRITE_PERF_MAP");
+ if (Q_UNLIKELY(doProfile)) {
+ static QFile perfMapFile(QString::fromLatin1("/tmp/perf-%1.map")
+ .arg(QCoreApplication::applicationPid()));
+ static const bool isOpen = perfMapFile.open(QIODevice::WriteOnly);
+ if (!isOpen) {
+ qWarning("QV4::JIT::Assembler: Cannot write perf map file.");
+ doProfile = false;
+ } else {
+ const void *address = codeRef->code().executableAddress();
+ perfMapFile.write(QByteArray::number(reinterpret_cast<quintptr>(address), 16));
+ perfMapFile.putChar(' ');
+ perfMapFile.write(QByteArray::number(static_cast<qsizetype>(codeRef->size()), 16));
+ perfMapFile.putChar(' ');
+ perfMapFile.write(Function::prettyName(function, address).toUtf8());
+ perfMapFile.putChar('\n');
+ perfMapFile.flush();
+ }
+ }
+}
+
+void destroyFunctionTable(Function *function, JSC::MacroAssemblerCodeRef *codeRef)
+{
+ Q_UNUSED(function);
+ Q_UNUSED(codeRef);
+
+ // It's not advisable to remove things from the perf map file, as it's primarily used to analyze
+ // a trace after the application has terminated. We want to know about all functions that were
+ // ever jitted then. If the memory ranges overlap, we will have a problem when analyzing the
+ // trace. The JIT should try to avoid this.
+}
+
+size_t exceptionHandlerSize()
+{
+ return 0;
+}
+
+} // QV4
+
+QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4functiontable_win64.cpp b/src/qml/jsruntime/qv4functiontable_win64.cpp
new file mode 100644
index 0000000000..bc5b24f6cd
--- /dev/null
+++ b/src/qml/jsruntime/qv4functiontable_win64.cpp
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4functiontable_p.h"
+
+#include <assembler/MacroAssemblerCodeRef.h>
+
+#include <QtCore/qdebug.h>
+
+#include <Windows.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+enum UnwindOpcode: UINT8
+{
+ UWOP_PUSH_NONVOL = 0, /* info == register number */
+ UWOP_ALLOC_LARGE, /* no info, alloc size in next 2 slots */
+ UWOP_ALLOC_SMALL, /* info == size of allocation / 8 - 1 */
+ UWOP_SET_FPREG, /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */
+ UWOP_SAVE_NONVOL, /* info == register number, offset in next slot */
+ UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */
+ UWOP_SAVE_XMM128 = 8, /* info == XMM reg number, offset in next slot */
+ UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */
+ UWOP_PUSH_MACHFRAME /* info == 0: no error-code, 1: error-code */
+};
+
+enum Register : UINT8
+{
+ RAX = 0,
+ RCX,
+ RDX,
+ RBX,
+ RSP,
+ RBP,
+ RSI,
+ RDI,
+ NONE = 15
+};
+
+struct UnwindCode
+{
+ UnwindCode(UINT8 offset, UnwindOpcode operation, Register info)
+ : offset(offset), operation(operation), info(info)
+ {}
+
+ UINT8 offset;
+ UINT8 operation: 4;
+ UINT8 info: 4;
+};
+
+struct UnwindInfo
+{
+ UINT8 Version : 3;
+ UINT8 Flags : 5;
+ UINT8 SizeOfProlog;
+ UINT8 CountOfUnwindCodes;
+ UINT8 FrameRegister : 4;
+ UINT8 FrameRegisterOffset : 4;
+ UnwindCode UnwindCodes[2];
+};
+
+struct ExceptionHandlerRecord
+{
+ RUNTIME_FUNCTION handler;
+ UnwindInfo info;
+};
+
+void generateFunctionTable(Function *, JSC::MacroAssemblerCodeRef *codeRef)
+{
+ ExceptionHandlerRecord *record = reinterpret_cast<ExceptionHandlerRecord *>(
+ codeRef->executableMemory()->exceptionHandler());
+
+ record->info.Version = 1;
+ record->info.Flags = 0;
+ record->info.SizeOfProlog = 4;
+ record->info.CountOfUnwindCodes = 2;
+ record->info.FrameRegister = RBP;
+ record->info.FrameRegisterOffset = 0;
+
+ // Push frame pointer
+ record->info.UnwindCodes[1] = UnwindCode(1, UWOP_PUSH_NONVOL, RBP);
+ // Set frame pointer from stack pointer
+ record->info.UnwindCodes[0] = UnwindCode(4, UWOP_SET_FPREG, NONE);
+
+ const quintptr codeStart = quintptr(codeRef->code().executableAddress());
+ const quintptr codeSize = codeRef->size();
+
+ record->handler.BeginAddress = DWORD(codeStart - quintptr(record));
+ record->handler.EndAddress = DWORD(codeStart + codeSize - quintptr(record));
+ record->handler.UnwindData = offsetof(ExceptionHandlerRecord, info);
+
+ if (!RtlAddFunctionTable(&record->handler, 1, DWORD64(record))) {
+ const unsigned int errorCode = GetLastError();
+ qWarning() << "Failed to install win64 unwind hook. Error code:" << errorCode;
+ }
+}
+
+void destroyFunctionTable(Function *, JSC::MacroAssemblerCodeRef *codeRef)
+{
+ ExceptionHandlerRecord *record = reinterpret_cast<ExceptionHandlerRecord *>(
+ codeRef->executableMemory()->exceptionHandler());
+ if (!RtlDeleteFunctionTable(&record->handler)) {
+ const unsigned int errorCode = GetLastError();
+ qWarning() << "Failed to remove win64 unwind hook. Error code:" << errorCode;
+ }
+}
+
+size_t exceptionHandlerSize()
+{
+ return sizeof(ExceptionHandlerRecord);
+}
+
+} // QV4
+
+QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index ef0877dbd0..e4d8bcaafc 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -138,11 +138,14 @@ ReturnedValue VariantPrototype::method_toString(const FunctionObject *b, const V
const VariantObject *o = thisObject->as<QV4::VariantObject>();
if (!o)
RETURN_UNDEFINED();
- QString result = o->d()->data().toString();
- if (result.isEmpty() && !o->d()->data().canConvert(QVariant::String)) {
- result = QLatin1String("QVariant(")
- + QLatin1String(o->d()->data().typeName())
- + QLatin1Char(')');
+ const QVariant variant = o->d()->data();
+ QString result = variant.toString();
+ if (result.isEmpty() && !variant.canConvert(QVariant::String)) {
+ QDebug dbg(&result);
+ dbg << variant;
+ // QDebug appends a space, we're not interested in continuing the stream so we chop it off.
+ // Can't use nospace() because it would affect the debug-stream operator of the variant.
+ result.chop(1);
}
return Encode(v4->newString(result));
}
diff --git a/src/qml/parser/parser.pri b/src/qml/parser/parser.pri
index adab4ef9a2..2c0175c94b 100644
--- a/src/qml/parser/parser.pri
+++ b/src/qml/parser/parser.pri
@@ -8,7 +8,8 @@ HEADERS += \
$$PWD/qqmljsglobal_p.h \
$$PWD/qqmljskeywords_p.h \
$$PWD/qqmljsengine_p.h \
- $$PWD/qqmljsglobal_p.h
+ $$PWD/qqmljsglobal_p.h \
+ $$PWD/qqmljssourcelocation_p.h
SOURCES += \
$$PWD/qqmljsast.cpp \
diff --git a/src/qml/parser/qqmljsastfwd_p.h b/src/qml/parser/qqmljsastfwd_p.h
index 996264db59..7795e0ce71 100644
--- a/src/qml/parser/qqmljsastfwd_p.h
+++ b/src/qml/parser/qqmljsastfwd_p.h
@@ -41,6 +41,7 @@
#define QQMLJSAST_FWD_P_H
#include "qqmljsglobal_p.h"
+#include "qqmljssourcelocation_p.h"
#include <QtCore/qglobal.h>
@@ -59,27 +60,6 @@ QT_QML_BEGIN_NAMESPACE
namespace QQmlJS { namespace AST {
-class SourceLocation
-{
-public:
- explicit SourceLocation(quint32 offset = 0, quint32 length = 0, quint32 line = 0, quint32 column = 0)
- : offset(offset), length(length),
- startLine(line), startColumn(column)
- { }
-
- bool isValid() const { return length != 0; }
-
- quint32 begin() const { return offset; }
- quint32 end() const { return offset + length; }
-
-// attributes
- // ### encode
- quint32 offset;
- quint32 length;
- quint32 startLine;
- quint32 startColumn;
-};
-
class Visitor;
class Node;
class ExpressionNode;
diff --git a/src/qml/parser/qqmljsengine_p.h b/src/qml/parser/qqmljsengine_p.h
index 1de907d296..07b5026eb9 100644
--- a/src/qml/parser/qqmljsengine_p.h
+++ b/src/qml/parser/qqmljsengine_p.h
@@ -52,8 +52,8 @@
//
#include "qqmljsglobal_p.h"
-#include "qqmljsastfwd_p.h"
#include "qqmljsmemorypool_p.h"
+#include "qqmljssourcelocation_p.h"
#include <QtCore/qstring.h>
#include <QtCore/qset.h>
@@ -95,7 +95,7 @@ public:
class QML_PARSER_EXPORT DiagnosticMessage
{
public:
- enum Kind { Warning, Error };
+ enum Kind { Hint, Warning, Error };
DiagnosticMessage() {}
diff --git a/src/qml/parser/qqmljssourcelocation_p.h b/src/qml/parser/qqmljssourcelocation_p.h
new file mode 100644
index 0000000000..dc307ba168
--- /dev/null
+++ b/src/qml/parser/qqmljssourcelocation_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLJSSOURCELOCATION_P_H
+#define QQMLJSSOURCELOCATION_P_H
+
+#include "qqmljsglobal_p.h"
+
+#include <QtCore/qglobal.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QQmlJS { namespace AST {
+
+class SourceLocation
+{
+public:
+ explicit SourceLocation(quint32 offset = 0, quint32 length = 0, quint32 line = 0, quint32 column = 0)
+ : offset(offset), length(length),
+ startLine(line), startColumn(column)
+ { }
+
+ bool isValid() const { return length != 0; }
+
+ quint32 begin() const { return offset; }
+ quint32 end() const { return offset + length; }
+
+// attributes
+ // ### encode
+ quint32 offset;
+ quint32 length;
+ quint32 startLine;
+ quint32 startColumn;
+};
+
+} } // namespace AST
+
+QT_QML_END_NAMESPACE
+
+#endif
diff --git a/src/qml/qml.pro b/src/qml/qml.pro
index db59140f06..94717a8f43 100644
--- a/src/qml/qml.pro
+++ b/src/qml/qml.pro
@@ -73,6 +73,7 @@ include(jsruntime/jsruntime.pri)
include(jit/jit.pri)
include(qml/qml.pri)
include(debugger/debugger.pri)
+include(qmldirparser/qmldirparser.pri)
qtConfig(qml-animation) {
include(animations/animations.pri)
}
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index 6d69294c17..ca13ce9211 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -18,7 +18,6 @@ SOURCES += \
$$PWD/qqmlparserstatus.cpp \
$$PWD/qqmltypeloader.cpp \
$$PWD/qqmlinfo.cpp \
- $$PWD/qqmlerror.cpp \
$$PWD/qqmlvaluetype.cpp \
$$PWD/qqmlcleanup.cpp \
$$PWD/qqmlpropertycache.cpp \
@@ -44,7 +43,6 @@ SOURCES += \
$$PWD/qqmltypewrapper.cpp \
$$PWD/qqmlfileselector.cpp \
$$PWD/qqmlobjectcreator.cpp \
- $$PWD/qqmldirparser.cpp \
$$PWD/qqmldelayedcallqueue.cpp \
$$PWD/qqmlloggingcategory.cpp
@@ -81,7 +79,6 @@ HEADERS += \
$$PWD/qqmllist.h \
$$PWD/qqmllist_p.h \
$$PWD/qqmldata_p.h \
- $$PWD/qqmlerror.h \
$$PWD/qqmlvaluetype_p.h \
$$PWD/qqmlcleanup_p.h \
$$PWD/qqmlpropertycache_p.h \
@@ -112,7 +109,6 @@ HEADERS += \
$$PWD/qqmlfileselector_p.h \
$$PWD/qqmlfileselector.h \
$$PWD/qqmlobjectcreator_p.h \
- $$PWD/qqmldirparser_p.h \
$$PWD/qqmldelayedcallqueue_p.h \
$$PWD/qqmlloggingcategory_p.h
diff --git a/src/qml/qml/qqmlabstracturlinterceptor.h b/src/qml/qml/qqmlabstracturlinterceptor.h
index 665b37fb3a..af231f51b2 100644
--- a/src/qml/qml/qqmlabstracturlinterceptor.h
+++ b/src/qml/qml/qqmlabstracturlinterceptor.h
@@ -55,8 +55,8 @@ public:
UrlString = 0x1000
};
- QQmlAbstractUrlInterceptor() {}
- virtual ~QQmlAbstractUrlInterceptor() {}
+ QQmlAbstractUrlInterceptor() = default;
+ virtual ~QQmlAbstractUrlInterceptor() = default;
virtual QUrl intercept(const QUrl &path, DataType type) = 0;
};
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index e38f379eb0..024ec29a56 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -316,7 +316,7 @@ protected:
break;
default:
if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) {
- if (vtw->d()->valueType->typeId == pd->propType()) {
+ if (vtw->d()->valueType->metaType.id() == pd->propType()) {
return vtw->write(m_target.data(), pd->coreIndex());
}
}
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 3caa6ec138..70e188dc1c 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -64,7 +64,6 @@
#include "qqmlproperty_p.h"
#include "qqmlpropertycache_p.h"
#include "qqmlmetatype_p.h"
-#include "qqmldirparser_p.h"
#include <private/qintrusivelist_p.h>
#include <private/qrecyclepool_p.h>
#include <private/qfieldlist_p.h>
@@ -80,6 +79,7 @@
#include <private/qv8engine_p.h>
#include <private/qjsengine_p.h>
+#include <private/qqmldirparser_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index 0c1ffbf3a0..ac2629979f 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -46,6 +46,7 @@
#include "qqmlscriptstring_p.h"
#include "qqmlbinding_p.h"
#include <private/qv8engine_p.h>
+#include <private/qqmlsourcecoordinate_p.h>
#include <QtCore/qdebug.h>
diff --git a/src/qml/qml/qqmlextensioninterface.h b/src/qml/qml/qqmlextensioninterface.h
index c2d20ef0a3..d2eb79c5c9 100644
--- a/src/qml/qml/qqmlextensioninterface.h
+++ b/src/qml/qml/qqmlextensioninterface.h
@@ -51,14 +51,14 @@ class QQmlEngine;
class Q_QML_EXPORT QQmlTypesExtensionInterface
{
public:
- virtual ~QQmlTypesExtensionInterface() {}
+ virtual ~QQmlTypesExtensionInterface() = default;
virtual void registerTypes(const char *uri) = 0;
};
class Q_QML_EXPORT QQmlExtensionInterface : public QQmlTypesExtensionInterface
{
public:
- ~QQmlExtensionInterface() override {}
+ ~QQmlExtensionInterface() override = default;
virtual void initializeEngine(QQmlEngine *engine, const char *uri) = 0;
};
diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index 302fdd56c4..818537560c 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -174,16 +174,6 @@ T qmlobject_cast(QObject *object)
return 0;
}
-inline quint16 qmlSourceCoordinate(int n)
-{
- return (n > 0 && n <= static_cast<int>(USHRT_MAX)) ? static_cast<quint16>(n) : 0;
-}
-
-inline int qmlSourceCoordinate(quint16 n)
-{
- return (n == 0) ? -1 : static_cast<int>(n);
-}
-
#define IS_SIGNAL_CONNECTED(Sender, SenderType, Name, Arguments) \
do { \
QObject *sender = (Sender); \
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 11806a89a0..083917d20f 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -1087,13 +1087,6 @@ QString QQmlType::noCreationReason() const
return d->extraData.cd->noCreationReason;
}
-int QQmlType::createSize() const
-{
- if (!d || d->regType != CppType)
- return 0;
- return d->extraData.cd->allocationSize;
-}
-
bool QQmlType::isCreatable() const
{
return d && d->regType == CppType && d->extraData.cd->newFunc;
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index b3ca6acd64..2a45ddb4bb 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -196,8 +196,6 @@ public:
typedef void (*CreateFunc)(void *);
CreateFunc createFunction() const;
- int createSize() const;
-
QQmlCustomParser *customParser() const;
bool isCreatable() const;
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 9df502f778..fc48957bcb 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -1891,8 +1891,6 @@ bool QQmlTypeLoader::fileExists(const QString &path, const QString &file)
if (!fileSet)
return false;
- QString absoluteFilePath;
-
bool *value = fileSet->object(file);
if (value) {
return *value;
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 2b21591017..e92488f9f6 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -191,7 +191,6 @@ void QQmlValueTypeFactory::registerValueTypes(const char *uri, int versionMajor,
QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject)
: gadgetPtr(QMetaType::create(typeId))
- , typeId(typeId)
, metaType(typeId)
{
QObjectPrivate *op = QObjectPrivate::get(this);
@@ -230,12 +229,12 @@ void QQmlValueType::write(QObject *obj, int idx, QQmlPropertyData::WriteFlags fl
QVariant QQmlValueType::value()
{
Q_ASSERT(gadgetPtr);
- return QVariant(typeId, gadgetPtr);
+ return QVariant(metaType.id(), gadgetPtr);
}
void QQmlValueType::setValue(const QVariant &value)
{
- Q_ASSERT(typeId == value.userType());
+ Q_ASSERT(metaType.id() == value.userType());
metaType.destruct(gadgetPtr);
metaType.construct(gadgetPtr, value.constData());
}
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index 4ea71e8955..89f1b71d61 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -84,7 +84,6 @@ private:
void *gadgetPtr;
public:
- int typeId;
QMetaType metaType;
};
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index b503d75a47..9ce1c82f09 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -105,7 +105,7 @@ void Heap::QQmlValueTypeWrapper::destroy()
void Heap::QQmlValueTypeWrapper::setValue(const QVariant &value) const
{
- Q_ASSERT(valueType->typeId == value.userType());
+ Q_ASSERT(valueType->metaType.id() == value.userType());
if (gadgetPtr)
valueType->metaType.destruct(gadgetPtr);
if (!gadgetPtr)
@@ -116,7 +116,7 @@ void Heap::QQmlValueTypeWrapper::setValue(const QVariant &value) const
QVariant Heap::QQmlValueTypeWrapper::toVariant() const
{
Q_ASSERT(gadgetPtr);
- return QVariant(valueType->typeId, gadgetPtr);
+ return QVariant(valueType->metaType.id(), gadgetPtr);
}
@@ -221,7 +221,7 @@ bool QQmlValueTypeWrapper::toGadget(void *data) const
if (const QQmlValueTypeReference *ref = as<const QQmlValueTypeReference>())
if (!ref->readReferenceValue())
return false;
- const int typeId = d()->valueType->typeId;
+ const int typeId = d()->valueType->metaType.id();
QMetaType::destruct(typeId, data);
QMetaType::construct(typeId, data, d()->gadgetPtr);
return true;
@@ -305,7 +305,7 @@ bool QQmlValueTypeWrapper::isEqual(const QVariant& value) const
int QQmlValueTypeWrapper::typeId() const
{
- return d()->valueType->typeId;
+ return d()->valueType->metaType.id();
}
bool QQmlValueTypeWrapper::write(QObject *target, int propertyIndex) const
@@ -352,10 +352,10 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(const FunctionObject *b, con
// Prepare a buffer to pass to QMetaType::convert()
QString convertResult;
convertResult.~QString();
- if (QMetaType::convert(w->d()->gadgetPtr, w->d()->valueType->typeId, &convertResult, QMetaType::QString)) {
+ if (QMetaType::convert(w->d()->gadgetPtr, w->d()->valueType->metaType.id(), &convertResult, QMetaType::QString)) {
result = convertResult;
} else {
- result += QString::fromUtf8(QMetaType::typeName(w->d()->valueType->typeId))
+ result += QString::fromUtf8(QMetaType::typeName(w->d()->valueType->metaType.id()))
+ QLatin1Char('(');
const QMetaObject *mo = w->d()->propertyCache()->metaObject();
const int propCount = mo->propertyCount();
diff --git a/src/qml/qmldirparser/qmldirparser.pri b/src/qml/qmldirparser/qmldirparser.pri
new file mode 100644
index 0000000000..660e7b395a
--- /dev/null
+++ b/src/qml/qmldirparser/qmldirparser.pri
@@ -0,0 +1,11 @@
+INCLUDEPATH += $$PWD
+INCLUDEPATH += $$OUT_PWD
+
+HEADERS += \
+ $$PWD/qqmldirparser_p.h \
+ $$PWD/qqmlerror.h \
+ $$PWD/qqmlsourcecoordinate_p.h
+
+SOURCES += \
+ $$PWD/qqmldirparser.cpp \
+ $$PWD/qqmlerror.cpp
diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qmldirparser/qqmldirparser.cpp
index d87bf433b8..e944b52e47 100644
--- a/src/qml/qml/qqmldirparser.cpp
+++ b/src/qml/qmldirparser/qqmldirparser.cpp
@@ -367,12 +367,10 @@ QList<QQmlDirParser::Script> QQmlDirParser::scripts() const
return _scripts;
}
-#ifdef QT_CREATOR
QList<QQmlDirParser::TypeInfo> QQmlDirParser::typeInfos() const
{
return _typeInfos;
}
-#endif
bool QQmlDirParser::designerSupported() const
{
diff --git a/src/qml/qml/qqmldirparser_p.h b/src/qml/qmldirparser/qqmldirparser_p.h
index d7e29813d1..cff9cb11a4 100644
--- a/src/qml/qml/qqmldirparser_p.h
+++ b/src/qml/qmldirparser/qqmldirparser_p.h
@@ -122,7 +122,6 @@ public:
QList<Plugin> plugins() const;
bool designerSupported() const;
-#ifdef QT_CREATOR
struct TypeInfo
{
TypeInfo() {}
@@ -133,7 +132,6 @@ public:
};
QList<TypeInfo> typeInfos() const;
-#endif
QString className() const;
@@ -149,9 +147,7 @@ private:
QList<Script> _scripts;
QList<Plugin> _plugins;
bool _designerSupported;
-#ifdef QT_CREATOR
QList<TypeInfo> _typeInfos;
-#endif
QString _className;
};
diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qmldirparser/qqmlerror.cpp
index 61e9a3f37e..5e181f7e27 100644
--- a/src/qml/qml/qqmlerror.cpp
+++ b/src/qml/qmldirparser/qqmlerror.cpp
@@ -38,15 +38,17 @@
****************************************************************************/
#include "qqmlerror.h"
-#include "qqmlglobal_p.h"
+#include "qqmlsourcecoordinate_p.h"
#include <QtCore/qdebug.h>
#include <QtCore/qfile.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qvector.h>
-#include <QtCore/qpointer.h>
-#include <private/qv4errorobject_p.h>
+#ifndef QT_NO_QOBJECT
+#include <QtCore/qobject.h>
+#include <QtCore/qpointer.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -85,11 +87,13 @@ public:
quint16 line;
quint16 column;
QtMsgType messageType;
+#ifndef QT_NO_QOBJECT
QPointer<QObject> object;
+#endif
};
QQmlErrorPrivate::QQmlErrorPrivate()
-: line(0), column(0), messageType(QtMsgType::QtWarningMsg), object()
+: line(0), column(0), messageType(QtMsgType::QtWarningMsg)
{
}
@@ -125,7 +129,9 @@ QQmlError &QQmlError::operator=(const QQmlError &other)
d->description = other.d->description;
d->line = other.d->line;
d->column = other.d->column;
+#ifndef QT_NO_QOBJECT
d->object = other.d->object;
+#endif
d->messageType = other.d->messageType;
}
return *this;
@@ -227,6 +233,7 @@ void QQmlError::setColumn(int column)
d->column = qmlSourceCoordinate(column);
}
+#ifndef QT_NO_QOBJECT
/*!
Returns the nearest object where this error occurred.
Exceptions in bound property expressions set this to the object
@@ -249,6 +256,7 @@ void QQmlError::setObject(QObject *object)
d = new QQmlErrorPrivate;
d->object = object;
}
+#endif // QT_NO_QOBJECT
/*!
\since 5.9
diff --git a/src/qml/qml/qqmlerror.h b/src/qml/qmldirparser/qqmlerror.h
index ef529e3828..f4221358e9 100644
--- a/src/qml/qml/qqmlerror.h
+++ b/src/qml/qmldirparser/qqmlerror.h
@@ -68,8 +68,12 @@ public:
void setLine(int);
int column() const;
void setColumn(int);
+
+#ifndef QT_NO_QOBJECT
QObject *object() const;
void setObject(QObject *);
+#endif
+
QtMsgType messageType() const;
void setMessageType(QtMsgType messageType);
diff --git a/src/qml/qmldirparser/qqmlsourcecoordinate_p.h b/src/qml/qmldirparser/qqmlsourcecoordinate_p.h
new file mode 100644
index 0000000000..76ac741ae8
--- /dev/null
+++ b/src/qml/qmldirparser/qqmlsourcecoordinate_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLSOURCECOORDINATE_P_H
+#define QQMLSOURCECOORDINATE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+#include <climits>
+
+QT_BEGIN_NAMESPACE
+
+inline quint16 qmlSourceCoordinate(int n)
+{
+ return (n > 0 && n <= static_cast<int>(USHRT_MAX)) ? static_cast<quint16>(n) : 0;
+}
+
+inline int qmlSourceCoordinate(quint16 n)
+{
+ return (n == 0) ? -1 : static_cast<int>(n);
+}
+
+QT_END_NAMESPACE
+
+#endif // QQMLSOURCECOORDINATE_P_H
diff --git a/src/qmldebug/qmldebug.pro b/src/qmldebug/qmldebug.pro
index 0807482d23..94d300b765 100644
--- a/src/qmldebug/qmldebug.pro
+++ b/src/qmldebug/qmldebug.pro
@@ -9,20 +9,27 @@ SOURCES += \
qqmldebugconnection.cpp \
qqmldebugmessageclient.cpp \
qqmlenginecontrolclient.cpp \
+ qqmlenginedebugclient.cpp \
+ qqmlinspectorclient.cpp \
qqmlpreviewclient.cpp \
qqmlprofilerclient.cpp \
qqmlprofilerevent.cpp \
qqmlprofilereventlocation.cpp \
qqmlprofilereventtype.cpp \
- qqmlprofilertypedevent.cpp
+ qqmlprofilertypedevent.cpp \
+ qv4debugclient.cpp
HEADERS += \
qqmldebugclient_p.h \
qqmldebugclient_p_p.h \
qqmldebugconnection_p.h \
qqmldebugmessageclient_p.h \
+ qqmlenginedebugclient_p.h \
+ qqmlenginedebugclient_p_p.h \
qqmlenginecontrolclient_p.h \
qqmlenginecontrolclient_p_p.h \
+ qqmlinspectorclient_p.h \
+ qqmlinspectorclient_p_p.h \
qqmlpreviewclient_p.h \
qqmlpreviewclient_p_p.h \
qqmlprofilerclient_p.h \
@@ -32,4 +39,6 @@ HEADERS += \
qqmlprofilereventreceiver_p.h \
qqmlprofilereventtype_p.h \
qqmlprofilertypedevent_p.h \
- qqmlprofilerclientdefinitions_p.h
+ qqmlprofilerclientdefinitions_p.h \
+ qv4debugclient_p.h \
+ qv4debugclient_p_p.h
diff --git a/src/qmldebug/qqmlenginedebugclient.cpp b/src/qmldebug/qqmlenginedebugclient.cpp
new file mode 100644
index 0000000000..ec45ec33bc
--- /dev/null
+++ b/src/qmldebug/qqmlenginedebugclient.cpp
@@ -0,0 +1,566 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE: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$
+**
+****************************************************************************/
+
+#include "qqmlenginedebugclient_p_p.h"
+#include <private/qqmldebugconnection_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QQmlObjectData {
+ QUrl url;
+ int lineNumber = -1;
+ int columnNumber = -1;
+ QString idString;
+ QString objectName;
+ QString objectType;
+ int objectId = -1;
+ int contextId = -1;
+ int parentId = -1;
+};
+
+QPacket &operator>>(QPacket &ds, QQmlObjectData &data)
+{
+ ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
+ >> data.objectName >> data.objectType >> data.objectId >> data.contextId
+ >> data.parentId;
+ return ds;
+}
+
+struct QQmlObjectProperty {
+ enum Type { Unknown, Basic, Object, List, SignalProperty };
+ Type type = Unknown;
+ QString name;
+ QVariant value;
+ QString valueTypeName;
+ QString binding;
+ bool hasNotifySignal = false;
+};
+
+QPacket &operator>>(QPacket &ds, QQmlObjectProperty &data)
+{
+ int type;
+ ds >> type >> data.name >> data.value >> data.valueTypeName
+ >> data.binding >> data.hasNotifySignal;
+ data.type = (QQmlObjectProperty::Type)type;
+ return ds;
+}
+
+QQmlEngineDebugClient::QQmlEngineDebugClient(QQmlDebugConnection *connection) :
+ QQmlDebugClient(*new QQmlEngineDebugClientPrivate(connection))
+{
+}
+
+QQmlEngineDebugClientPrivate::QQmlEngineDebugClientPrivate(QQmlDebugConnection *connection) :
+ QQmlDebugClientPrivate (QLatin1String("QmlDebugger"), connection)
+{
+}
+
+
+quint32 QQmlEngineDebugClient::addWatch(
+ const QQmlEngineDebugPropertyReference &property, bool *success)
+{
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("WATCH_PROPERTY") << id << property.objectDebugId
+ << property.name.toUtf8();
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::addWatch(
+ const QQmlEngineDebugContextReference &, const QString &, bool *success)
+{
+ *success = false;
+ qWarning("QQmlEngineDebugClient::addWatch(): Not implemented");
+ return 0;
+}
+
+quint32 QQmlEngineDebugClient::addWatch(
+ const QQmlEngineDebugObjectReference &object, const QString &expr,
+ bool *success)
+{
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("WATCH_EXPR_OBJECT") << id << object.debugId << expr;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::addWatch(
+ const QQmlEngineDebugObjectReference &object, bool *success)
+{
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("WATCH_OBJECT") << id << object.debugId;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::addWatch(
+ const QQmlEngineDebugFileReference &, bool *success)
+{
+ *success = false;
+ qWarning("QQmlEngineDebugClient::addWatch(): Not implemented");
+ return 0;
+}
+
+void QQmlEngineDebugClient::removeWatch(quint32 id, bool *success)
+{
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("NO_WATCH") << id;
+ sendMessage(ds.data());
+ *success = true;
+ }
+}
+
+quint32 QQmlEngineDebugClient::queryAvailableEngines(bool *success)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->engines.clear();
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("LIST_ENGINES") << id;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryRootContexts(
+ const QQmlEngineDebugEngineReference &engine, bool *success)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->rootContext = QQmlEngineDebugContextReference();
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && engine.debugId != -1) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("LIST_OBJECTS") << id << engine.debugId;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryObject(
+ const QQmlEngineDebugObjectReference &object, bool *success)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->object = QQmlEngineDebugObjectReference();
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && object.debugId != -1) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("FETCH_OBJECT") << id << object.debugId << false << true;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryObjectsForLocation(
+ const QString &file, int lineNumber, int columnNumber, bool *success)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->objects.clear();
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("FETCH_OBJECTS_FOR_LOCATION") << id << file << lineNumber
+ << columnNumber << false << true;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryObjectRecursive(
+ const QQmlEngineDebugObjectReference &object, bool *success)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->object = QQmlEngineDebugObjectReference();
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && object.debugId != -1) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("FETCH_OBJECT") << id << object.debugId << true << true;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryObjectsForLocationRecursive(const QString &file,
+ int lineNumber, int columnNumber, bool *success)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->objects.clear();
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("FETCH_OBJECTS_FOR_LOCATION") << id << file << lineNumber
+ << columnNumber << true << true;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryExpressionResult(
+ int objectDebugId, const QString &expr, bool *success)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->exprResult = QVariant();
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("EVAL_EXPRESSION") << id << objectDebugId << expr
+ << engines()[0].debugId;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryExpressionResultBC(
+ int objectDebugId, const QString &expr, bool *success)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->exprResult = QVariant();
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("EVAL_EXPRESSION") << id << objectDebugId << expr;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::setBindingForObject(
+ int objectDebugId,
+ const QString &propertyName,
+ const QVariant &bindingExpression,
+ bool isLiteralValue,
+ const QString &source, int line,
+ bool *success)
+{
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("SET_BINDING") << id << objectDebugId << propertyName
+ << bindingExpression << isLiteralValue << source << line;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::resetBindingForObject(
+ int objectDebugId,
+ const QString &propertyName,
+ bool *success)
+{
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("RESET_BINDING") << id << objectDebugId << propertyName;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::setMethodBody(
+ int objectDebugId, const QString &methodName,
+ const QString &methodBody, bool *success)
+{
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("SET_METHOD_BODY") << id << objectDebugId
+ << methodName << methodBody;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+void QQmlEngineDebugClient::decode(QPacket &ds,
+ QQmlEngineDebugObjectReference &o,
+ bool simple)
+{
+ QQmlObjectData data;
+ ds >> data;
+ o.debugId = data.objectId;
+ o.className = data.objectType;
+ o.idString = data.idString;
+ o.name = data.objectName;
+ o.source.url = data.url;
+ o.source.lineNumber = data.lineNumber;
+ o.source.columnNumber = data.columnNumber;
+ o.contextDebugId = data.contextId;
+
+ if (simple)
+ return;
+
+ int childCount;
+ bool recur;
+ ds >> childCount >> recur;
+
+ for (int ii = 0; ii < childCount; ++ii) {
+ o.children.append(QQmlEngineDebugObjectReference());
+ decode(ds, o.children.last(), !recur);
+ }
+
+ int propCount;
+ ds >> propCount;
+
+ for (int ii = 0; ii < propCount; ++ii) {
+ QQmlObjectProperty data;
+ ds >> data;
+ QQmlEngineDebugPropertyReference prop;
+ prop.objectDebugId = o.debugId;
+ prop.name = data.name;
+ prop.binding = data.binding;
+ prop.hasNotifySignal = data.hasNotifySignal;
+ prop.valueTypeName = data.valueTypeName;
+ switch (data.type) {
+ case QQmlObjectProperty::Basic:
+ case QQmlObjectProperty::List:
+ case QQmlObjectProperty::SignalProperty:
+ {
+ prop.value = data.value;
+ break;
+ }
+ case QQmlObjectProperty::Object:
+ {
+ QQmlEngineDebugObjectReference obj;
+ obj.name = data.value.toString();
+ obj.className = prop.valueTypeName;
+ prop.value = qVariantFromValue(obj);
+ break;
+ }
+ case QQmlObjectProperty::Unknown:
+ break;
+ }
+ o.properties << prop;
+ }
+}
+
+void QQmlEngineDebugClient::decode(QPacket &ds,
+ QList<QQmlEngineDebugObjectReference> &o,
+ bool simple)
+{
+ int count;
+ ds >> count;
+ for (int i = 0; i < count; i++) {
+ QQmlEngineDebugObjectReference obj;
+ decode(ds, obj, simple);
+ o << obj;
+ }
+}
+
+QList<QQmlEngineDebugEngineReference> QQmlEngineDebugClient::engines() const
+{
+ Q_D(const QQmlEngineDebugClient);
+ return d->engines;
+}
+
+QQmlEngineDebugContextReference QQmlEngineDebugClient::rootContext() const
+{
+ Q_D(const QQmlEngineDebugClient);
+ return d->rootContext;
+}
+
+QQmlEngineDebugObjectReference QQmlEngineDebugClient::object() const
+{
+ Q_D(const QQmlEngineDebugClient);
+ return d->object;
+}
+
+QList<QQmlEngineDebugObjectReference> QQmlEngineDebugClient::objects() const
+{
+ Q_D(const QQmlEngineDebugClient);
+ return d->objects;
+}
+
+QVariant QQmlEngineDebugClient::resultExpr() const
+{
+ Q_D(const QQmlEngineDebugClient);
+ return d->exprResult;
+}
+
+bool QQmlEngineDebugClient::valid() const
+{
+ Q_D(const QQmlEngineDebugClient);
+ return d->valid;
+}
+
+void QQmlEngineDebugClient::decode(QPacket &ds,
+ QQmlEngineDebugContextReference &c)
+{
+ ds >> c.name >> c.debugId;
+
+ int contextCount;
+ ds >> contextCount;
+
+ for (int ii = 0; ii < contextCount; ++ii) {
+ c.contexts.append(QQmlEngineDebugContextReference());
+ decode(ds, c.contexts.last());
+ }
+
+ int objectCount;
+ ds >> objectCount;
+
+ for (int ii = 0; ii < objectCount; ++ii) {
+ QQmlEngineDebugObjectReference obj;
+ decode(ds, obj, true);
+
+ obj.contextDebugId = c.debugId;
+ c.objects << obj;
+ }
+}
+
+void QQmlEngineDebugClient::messageReceived(const QByteArray &data)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->valid = false;
+ QPacket ds(connection()->currentDataStreamVersion(), data);
+
+ int queryId;
+ QByteArray type;
+ ds >> type >> queryId;
+
+ //qDebug() << "QQmlEngineDebugPrivate::message()" << type;
+
+ if (type == "LIST_ENGINES_R") {
+ int count;
+ ds >> count;
+
+ d->engines.clear();
+ for (int ii = 0; ii < count; ++ii) {
+ QQmlEngineDebugEngineReference eng;
+ ds >> eng.name;
+ ds >> eng.debugId;
+ d->engines << eng;
+ }
+ } else if (type == "LIST_OBJECTS_R") {
+ if (!ds.atEnd())
+ decode(ds, d->rootContext);
+
+ } else if (type == "FETCH_OBJECT_R") {
+ if (!ds.atEnd())
+ decode(ds, d->object, false);
+
+ } else if (type == "FETCH_OBJECTS_FOR_LOCATION_R") {
+ if (!ds.atEnd())
+ decode(ds, d->objects, false);
+
+ } else if (type == "EVAL_EXPRESSION_R") {;
+ ds >> d->exprResult;
+
+ } else if (type == "WATCH_PROPERTY_R") {
+ ds >> d->valid;
+
+ } else if (type == "WATCH_OBJECT_R") {
+ ds >> d->valid;
+
+ } else if (type == "WATCH_EXPR_OBJECT_R") {
+ ds >> d->valid;
+
+ } else if (type == "UPDATE_WATCH") {
+ int debugId;
+ QByteArray name;
+ QVariant value;
+ ds >> debugId >> name >> value;
+ emit valueChanged(name, value);
+ return;
+
+ } else if (type == "OBJECT_CREATED") {
+ int engineId, objectId, parentId;
+ ds >> engineId >> objectId >> parentId;
+ emit newObject(objectId);
+ return;
+ } else if (type == "SET_BINDING_R") {
+ ds >> d->valid;
+ } else if (type == "RESET_BINDING_R") {
+ ds >> d->valid;
+ } else if (type == "SET_METHOD_BODY_R") {
+ ds >> d->valid;
+ } else if (type == "NO_WATCH_R") {
+ ds >> d->valid;
+ }
+ emit result();
+}
+
+
+quint32 QQmlEngineDebugClient::getId()
+{
+ Q_D(QQmlEngineDebugClient);
+ return d->nextId++;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmlenginedebugclient_p.h b/src/qmldebug/qqmlenginedebugclient_p.h
new file mode 100644
index 0000000000..4a9cc3a020
--- /dev/null
+++ b/src/qmldebug/qqmlenginedebugclient_p.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE: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$
+**
+****************************************************************************/
+
+#ifndef QQMLENGINEDEBUGCLIENT_H
+#define QQMLENGINEDEBUGCLIENT_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qqmldebugclient_p.h>
+#include <private/qpacket_p.h>
+
+#include <QtCore/qurl.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QQmlEngineDebugPropertyReference
+{
+ int objectDebugId = -1;
+ QString name;
+ QVariant value;
+ QString valueTypeName;
+ QString binding;
+ bool hasNotifySignal = false;
+};
+
+struct QQmlEngineDebugFileReference
+{
+ QUrl url;
+ int lineNumber = -1;
+ int columnNumber = -1;
+};
+
+struct QQmlEngineDebugObjectReference
+{
+ int debugId = -1;
+ QString className;
+ QString idString;
+ QString name;
+ QQmlEngineDebugFileReference source;
+ int contextDebugId = -1;
+ QList<QQmlEngineDebugPropertyReference> properties;
+ QList<QQmlEngineDebugObjectReference> children;
+};
+
+struct QQmlEngineDebugContextReference
+{
+ int debugId = -1;
+ QString name;
+ QList<QQmlEngineDebugObjectReference> objects;
+ QList<QQmlEngineDebugContextReference> contexts;
+};
+
+struct QQmlEngineDebugEngineReference
+{
+ int debugId = -1;
+ QString name;
+};
+
+class QQmlEngineDebugClientPrivate;
+class QQmlEngineDebugClient : public QQmlDebugClient
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQmlEngineDebugClient)
+
+public:
+ explicit QQmlEngineDebugClient(QQmlDebugConnection *conn);
+
+ quint32 addWatch(const QQmlEngineDebugPropertyReference &,
+ bool *success);
+ quint32 addWatch(const QQmlEngineDebugContextReference &, const QString &,
+ bool *success);
+ quint32 addWatch(const QQmlEngineDebugObjectReference &, const QString &,
+ bool *success);
+ quint32 addWatch(const QQmlEngineDebugObjectReference &,
+ bool *success);
+ quint32 addWatch(const QQmlEngineDebugFileReference &,
+ bool *success);
+
+ void removeWatch(quint32 watch, bool *success);
+
+ quint32 queryAvailableEngines(bool *success);
+ quint32 queryRootContexts(const QQmlEngineDebugEngineReference &,
+ bool *success);
+ quint32 queryObject(const QQmlEngineDebugObjectReference &,
+ bool *success);
+ quint32 queryObjectsForLocation(const QString &file,
+ int lineNumber, int columnNumber, bool *success);
+ quint32 queryObjectRecursive(const QQmlEngineDebugObjectReference &,
+ bool *success);
+ quint32 queryObjectsForLocationRecursive(const QString &file,
+ int lineNumber, int columnNumber, bool *success);
+ quint32 queryExpressionResult(int objectDebugId,
+ const QString &expr,
+ bool *success);
+ quint32 queryExpressionResultBC(int objectDebugId,
+ const QString &expr,
+ bool *success);
+ quint32 setBindingForObject(int objectDebugId, const QString &propertyName,
+ const QVariant &bindingExpression,
+ bool isLiteralValue,
+ const QString &source, int line, bool *success);
+ quint32 resetBindingForObject(int objectDebugId,
+ const QString &propertyName, bool *success);
+ quint32 setMethodBody(int objectDebugId, const QString &methodName,
+ const QString &methodBody, bool *success);
+
+ quint32 getId();
+
+ void decode(QPacket &ds, QQmlEngineDebugContextReference &);
+ void decode(QPacket &ds, QQmlEngineDebugObjectReference &, bool simple);
+ void decode(QPacket &ds, QList<QQmlEngineDebugObjectReference> &o, bool simple);
+
+ QList<QQmlEngineDebugEngineReference> engines() const;
+ QQmlEngineDebugContextReference rootContext() const;
+ QQmlEngineDebugObjectReference object() const;
+ QList<QQmlEngineDebugObjectReference> objects() const;
+ QVariant resultExpr() const;
+ bool valid() const;
+
+signals:
+ void newObject(int objectId);
+ void valueChanged(QByteArray,QVariant);
+ void result();
+
+protected:
+ void messageReceived(const QByteArray &) override;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QQmlEngineDebugObjectReference)
+
+#endif // QQMLENGINEDEBUGCLIENT_H
diff --git a/src/qmldebug/qqmlenginedebugclient_p_p.h b/src/qmldebug/qqmlenginedebugclient_p_p.h
new file mode 100644
index 0000000000..7c992ad3ab
--- /dev/null
+++ b/src/qmldebug/qqmlenginedebugclient_p_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLENGINEDEBUGCLIENT_P_P_H
+#define QQMLENGINEDEBUGCLIENT_P_P_H
+
+#include "qqmlenginedebugclient_p.h"
+#include "qqmldebugclient_p_p.h"
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlEngineDebugClientPrivate : public QQmlDebugClientPrivate
+{
+ Q_DECLARE_PUBLIC(QQmlEngineDebugClient)
+public:
+ QQmlEngineDebugClientPrivate(QQmlDebugConnection *connection);
+
+ quint32 nextId = 0;
+ bool valid = false;
+ QList<QQmlEngineDebugEngineReference> engines;
+ QQmlEngineDebugContextReference rootContext;
+ QQmlEngineDebugObjectReference object;
+ QList<QQmlEngineDebugObjectReference> objects;
+ QVariant exprResult;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLENGINEDEBUGCLIENT_P_P_H
diff --git a/src/qmldebug/qqmlinspectorclient.cpp b/src/qmldebug/qqmlinspectorclient.cpp
new file mode 100644
index 0000000000..1de52bd0c1
--- /dev/null
+++ b/src/qmldebug/qqmlinspectorclient.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlinspectorclient_p_p.h"
+
+#include <private/qpacket_p.h>
+#include <private/qqmldebugconnection_p.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlInspectorClient::QQmlInspectorClient(QQmlDebugConnection *connection) :
+ QQmlDebugClient(*new QQmlInspectorClientPrivate(connection))
+{
+}
+
+QQmlInspectorClientPrivate::QQmlInspectorClientPrivate(QQmlDebugConnection *connection) :
+ QQmlDebugClientPrivate(QLatin1String("QmlInspector"), connection)
+{
+}
+
+int QQmlInspectorClient::setInspectToolEnabled(bool enabled)
+{
+ Q_D(QQmlInspectorClient);
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("request") << ++(d->m_lastRequestId)
+ << QByteArray(enabled ? "enable" : "disable");
+
+ sendMessage(ds.data());
+ return d->m_lastRequestId;
+}
+
+int QQmlInspectorClient::setShowAppOnTop(bool showOnTop)
+{
+ Q_D(QQmlInspectorClient);
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("request") << ++(d->m_lastRequestId)
+ << QByteArray("showAppOnTop") << showOnTop;
+
+ sendMessage(ds.data());
+ return d->m_lastRequestId;
+}
+
+int QQmlInspectorClient::setAnimationSpeed(qreal speed)
+{
+ Q_D(QQmlInspectorClient);
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("request") << ++(d->m_lastRequestId)
+ << QByteArray("setAnimationSpeed") << speed;
+
+ sendMessage(ds.data());
+ return d->m_lastRequestId;
+}
+
+int QQmlInspectorClient::select(const QList<int> &objectIds)
+{
+ Q_D(QQmlInspectorClient);
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("request") << ++(d->m_lastRequestId)
+ << QByteArray("select") << objectIds;
+
+ sendMessage(ds.data());
+ return d->m_lastRequestId;
+}
+
+int QQmlInspectorClient::createObject(const QString &qml, int parentId, const QStringList &imports,
+ const QString &filename)
+{
+ Q_D(QQmlInspectorClient);
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("request") << ++(d->m_lastRequestId)
+ << QByteArray("createObject") << qml << parentId << imports << filename;
+ sendMessage(ds.data());
+ return d->m_lastRequestId;
+}
+
+int QQmlInspectorClient::moveObject(int childId, int newParentId)
+{
+ Q_D(QQmlInspectorClient);
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("request") << ++(d->m_lastRequestId)
+ << QByteArray("moveObject") << childId << newParentId;
+ sendMessage(ds.data());
+ return d->m_lastRequestId;
+}
+
+int QQmlInspectorClient::destroyObject(int objectId)
+{
+ Q_D(QQmlInspectorClient);
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("request") << ++(d->m_lastRequestId)
+ << QByteArray("destroyObject") << objectId;
+ sendMessage(ds.data());
+ return d->m_lastRequestId;
+}
+
+void QQmlInspectorClient::messageReceived(const QByteArray &message)
+{
+ QPacket ds(connection()->currentDataStreamVersion(), message);
+ QByteArray type;
+ ds >> type;
+
+ if (type != QByteArray("response")) {
+ qDebug() << "Unhandled message of type" << type;
+ return;
+ }
+
+ int responseId;
+ bool result;
+ ds >> responseId >> result;
+ emit responseReceived(responseId, result);
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmlinspectorclient_p.h b/src/qmldebug/qqmlinspectorclient_p.h
new file mode 100644
index 0000000000..3e502f4f45
--- /dev/null
+++ b/src/qmldebug/qqmlinspectorclient_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLINSPECTORCLIENT_P_H
+#define QQMLINSPECTORCLIENT_P_H
+
+#include <private/qqmldebugclient_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlInspectorClientPrivate;
+class QQmlInspectorClient : public QQmlDebugClient
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQmlInspectorClient)
+
+public:
+ QQmlInspectorClient(QQmlDebugConnection *connection);
+
+ int setInspectToolEnabled(bool enabled);
+ int setShowAppOnTop(bool showOnTop);
+ int setAnimationSpeed(qreal speed);
+ int select(const QList<int> &objectIds);
+ int createObject(const QString &qml, int parentId, const QStringList &imports,
+ const QString &filename);
+ int moveObject(int childId, int newParentId);
+ int destroyObject(int objectId);
+
+signals:
+ void responseReceived(int requestId, bool result);
+
+protected:
+ void messageReceived(const QByteArray &message) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLINSPECTORCLIENT_P_H
diff --git a/src/qmldebug/qqmlinspectorclient_p_p.h b/src/qmldebug/qqmlinspectorclient_p_p.h
new file mode 100644
index 0000000000..91537dd994
--- /dev/null
+++ b/src/qmldebug/qqmlinspectorclient_p_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLINSPECTORCLIENT_P_P_H
+#define QQMLINSPECTORCLIENT_P_P_H
+
+#include "qqmlinspectorclient_p.h"
+#include "qqmldebugclient_p_p.h"
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlInspectorClientPrivate : public QQmlDebugClientPrivate
+{
+ Q_DECLARE_PUBLIC(QQmlInspectorClient)
+public:
+ QQmlInspectorClientPrivate(QQmlDebugConnection *connection);
+ int m_lastRequestId = -1;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLINSPECTORCLIENT_P_P_H
diff --git a/src/qmldebug/qv4debugclient.cpp b/src/qmldebug/qv4debugclient.cpp
new file mode 100644
index 0000000000..76c2f1ebea
--- /dev/null
+++ b/src/qmldebug/qv4debugclient.cpp
@@ -0,0 +1,578 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4debugclient_p.h"
+#include "qv4debugclient_p_p.h"
+#include "qqmldebugconnection_p.h"
+
+#include <private/qpacket_p.h>
+
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonValue>
+#include <QJsonArray>
+
+QT_BEGIN_NAMESPACE
+
+const char *V8REQUEST = "v8request";
+const char *V8MESSAGE = "v8message";
+const char *SEQ = "seq";
+const char *TYPE = "type";
+const char *COMMAND = "command";
+const char *ARGUMENTS = "arguments";
+const char *STEPACTION = "stepaction";
+const char *STEPCOUNT = "stepcount";
+const char *EXPRESSION = "expression";
+const char *FRAME = "frame";
+const char *CONTEXT = "context";
+const char *GLOBAL = "global";
+const char *DISABLEBREAK = "disable_break";
+const char *HANDLES = "handles";
+const char *INCLUDESOURCE = "includeSource";
+const char *FROMFRAME = "fromFrame";
+const char *TOFRAME = "toFrame";
+const char *BOTTOM = "bottom";
+const char *NUMBER = "number";
+const char *FRAMENUMBER = "frameNumber";
+const char *TYPES = "types";
+const char *IDS = "ids";
+const char *FILTER = "filter";
+const char *FROMLINE = "fromLine";
+const char *TOLINE = "toLine";
+const char *TARGET = "target";
+const char *LINE = "line";
+const char *COLUMN = "column";
+const char *ENABLED = "enabled";
+const char *CONDITION = "condition";
+const char *IGNORECOUNT = "ignoreCount";
+const char *BREAKPOINT = "breakpoint";
+const char *FLAGS = "flags";
+
+const char *CONTINEDEBUGGING = "continue";
+const char *EVALUATE = "evaluate";
+const char *LOOKUP = "lookup";
+const char *BACKTRACE = "backtrace";
+const char *SCOPE = "scope";
+const char *SCOPES = "scopes";
+const char *SCRIPTS = "scripts";
+const char *SOURCE = "source";
+const char *SETBREAKPOINT = "setbreakpoint";
+const char *CLEARBREAKPOINT = "clearbreakpoint";
+const char *CHANGEBREAKPOINT = "changebreakpoint";
+const char *SETEXCEPTIONBREAK = "setexceptionbreak";
+const char *VERSION = "version";
+const char *DISCONNECT = "disconnect";
+const char *GARBAGECOLLECTOR = "gc";
+
+const char *CONNECT = "connect";
+const char *INTERRUPT = "interrupt";
+
+const char *REQUEST = "request";
+const char *IN = "in";
+const char *NEXT = "next";
+const char *OUT = "out";
+
+const char *SCRIPT = "script";
+const char *SCRIPTREGEXP = "scriptRegExp";
+const char *EVENT = "event";
+
+const char *ALL = "all";
+const char *UNCAUGHT = "uncaught";
+
+#define VARIANTMAPINIT \
+ Q_D(QV4DebugClient); \
+ QJsonObject jsonVal; \
+ jsonVal.insert(QLatin1String(SEQ), d->seq++); \
+ jsonVal.insert(QLatin1String(TYPE), QLatin1String(REQUEST));
+
+QV4DebugClient::QV4DebugClient(QQmlDebugConnection *connection)
+ : QQmlDebugClient(*new QV4DebugClientPrivate(connection))
+{
+ QObject::connect(this, &QQmlDebugClient::stateChanged,
+ this, [this](State state) { d_func()->onStateChanged(state); });
+}
+
+QV4DebugClientPrivate::QV4DebugClientPrivate(QQmlDebugConnection *connection) :
+ QQmlDebugClientPrivate(QLatin1String("V8Debugger"), connection)
+{
+}
+
+void QV4DebugClient::connect()
+{
+ Q_D(QV4DebugClient);
+ d->sendMessage(CONNECT);
+}
+
+void QV4DebugClient::interrupt()
+{
+ Q_D(QV4DebugClient);
+ d->sendMessage(INTERRUPT);
+}
+
+void QV4DebugClient::continueDebugging(StepAction action)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "continue",
+ // "arguments" : { "stepaction" : <"in", "next" or "out">,
+ // "stepcount" : <number of steps (default 1)>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(CONTINEDEBUGGING));
+
+ if (action != Continue) {
+ QJsonObject args;
+ switch (action) {
+ case In:
+ args.insert(QLatin1String(STEPACTION), QLatin1String(IN));
+ break;
+ case Out:
+ args.insert(QLatin1String(STEPACTION), QLatin1String(OUT));
+ break;
+ case Next:
+ args.insert(QLatin1String(STEPACTION), QLatin1String(NEXT));
+ break;
+ default:
+ break;
+ }
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+ }
+
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::evaluate(const QString &expr, int frame, int context)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "evaluate",
+ // "arguments" : { "expression" : <expression to evaluate>,
+ // "frame" : <number>,
+ // "context" : <object ID>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(EVALUATE));
+
+ QJsonObject args;
+ args.insert(QLatin1String(EXPRESSION), expr);
+
+ if (frame != -1)
+ args.insert(QLatin1String(FRAME), frame);
+
+ if (context != -1)
+ args.insert(QLatin1String(CONTEXT), context);
+
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::lookup(const QList<int> &handles, bool includeSource)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "lookup",
+ // "arguments" : { "handles" : <array of handles>,
+ // "includeSource" : <boolean indicating whether the source will be included when script objects are returned>,
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND),(QLatin1String(LOOKUP)));
+
+ QJsonObject args;
+ QJsonArray array;
+
+ for (int handle : handles)
+ array.append(handle);
+
+ args.insert(QLatin1String(HANDLES), array);
+
+ if (includeSource)
+ args.insert(QLatin1String(INCLUDESOURCE), includeSource);
+
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::backtrace(int fromFrame, int toFrame, bool bottom)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "backtrace",
+ // "arguments" : { "fromFrame" : <number>
+ // "toFrame" : <number>
+ // "bottom" : <boolean, set to true if the bottom of the stack is requested>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(BACKTRACE));
+
+ QJsonObject args;
+
+ if (fromFrame != -1)
+ args.insert(QLatin1String(FROMFRAME), fromFrame);
+
+ if (toFrame != -1)
+ args.insert(QLatin1String(TOFRAME), toFrame);
+
+ if (bottom)
+ args.insert(QLatin1String(BOTTOM), bottom);
+
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::frame(int number)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "frame",
+ // "arguments" : { "number" : <frame number>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(FRAME));
+
+ if (number != -1) {
+ QJsonObject args;
+ args.insert(QLatin1String(NUMBER), number);
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+ }
+
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::scope(int number, int frameNumber)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "scope",
+ // "arguments" : { "number" : <scope number>
+ // "frameNumber" : <frame number, optional uses selected frame if missing>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(SCOPE));
+
+ if (number != -1) {
+ QJsonObject args;
+ args.insert(QLatin1String(NUMBER), number);
+
+ if (frameNumber != -1)
+ args.insert(QLatin1String(FRAMENUMBER), frameNumber);
+
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+ }
+
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::scripts(int types, const QList<int> &ids, bool includeSource)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "scripts",
+ // "arguments" : { "types" : <types of scripts to retrieve
+ // set bit 0 for native scripts
+ // set bit 1 for extension scripts
+ // set bit 2 for normal scripts
+ // (default is 4 for normal scripts)>
+ // "ids" : <array of id's of scripts to return. If this is not specified all scripts are requrned>
+ // "includeSource" : <boolean indicating whether the source code should be included for the scripts returned>
+ // "filter" : <string or number: filter string or script id.
+ // If a number is specified, then only the script with the same number as its script id will be retrieved.
+ // If a string is specified, then only scripts whose names contain the filter string will be retrieved.>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(SCRIPTS));
+
+ QJsonObject args;
+ args.insert(QLatin1String(TYPES), types);
+
+ if (ids.count()) {
+ QJsonArray array;
+ for (int id : ids)
+ array.append(id);
+
+ args.insert(QLatin1String(IDS), array);
+ }
+
+ if (includeSource)
+ args.insert(QLatin1String(INCLUDESOURCE), includeSource);
+
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::setBreakpoint(const QString &target, int line, int column, bool enabled,
+ const QString &condition, int ignoreCount)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "setbreakpoint",
+ // "arguments" : { "type" : "scriptRegExp"
+ // "target" : <function expression or script identification>
+ // "line" : <line in script or function>
+ // "column" : <character position within the line>
+ // "enabled" : <initial enabled state. True or false, default is true>
+ // "condition" : <string with break point condition>
+ // "ignoreCount" : <number specifying the number of break point hits to ignore, default value is 0>
+ // }
+ // }
+
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(SETBREAKPOINT));
+
+ QJsonObject args;
+
+ args.insert(QLatin1String(TYPE), QLatin1String(SCRIPTREGEXP));
+ args.insert(QLatin1String(TARGET), target);
+
+ if (line != -1)
+ args.insert(QLatin1String(LINE), line);
+
+ if (column != -1)
+ args.insert(QLatin1String(COLUMN), column);
+
+ args.insert(QLatin1String(ENABLED), enabled);
+
+ if (!condition.isEmpty())
+ args.insert(QLatin1String(CONDITION), condition);
+
+ if (ignoreCount != -1)
+ args.insert(QLatin1String(IGNORECOUNT), ignoreCount);
+
+ jsonVal.insert(QLatin1String(ARGUMENTS),args);
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::clearBreakpoint(int breakpoint)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "clearbreakpoint",
+ // "arguments" : { "breakpoint" : <number of the break point to clear>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(CLEARBREAKPOINT));
+
+ QJsonObject args;
+ args.insert(QLatin1String(BREAKPOINT), breakpoint);
+ jsonVal.insert(QLatin1String(ARGUMENTS),args);
+
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::changeBreakpoint(int breakpoint, bool enabled)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "changebreakpoint",
+ // "arguments" : { "breakpoint" : <number of the break point to change>
+ // "enabled" : <bool: enables the break type if true, disables if false>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(CHANGEBREAKPOINT));
+
+ QJsonObject args;
+ args.insert(QLatin1String(BREAKPOINT), breakpoint);
+ args.insert(QLatin1String(ENABLED), enabled);
+
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::setExceptionBreak(Exception type, bool enabled)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "setexceptionbreak",
+ // "arguments" : { "type" : <string: "all", or "uncaught">,
+ // "enabled" : <optional bool: enables the break type if true>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(SETEXCEPTIONBREAK));
+
+ QJsonObject args;
+
+ if (type == All)
+ args.insert(QLatin1String(TYPE), QLatin1String(ALL));
+ else if (type == Uncaught)
+ args.insert(QLatin1String(TYPE), QLatin1String(UNCAUGHT));
+
+ if (enabled)
+ args.insert(QLatin1String(ENABLED), enabled);
+
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::version()
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "version",
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(VERSION));
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+QV4DebugClient::Response QV4DebugClient::response() const
+{
+ Q_D(const QV4DebugClient);
+ const QJsonObject value = QJsonDocument::fromJson(d->response).object();
+ return {
+ value.value(QLatin1String(COMMAND)).toString(),
+ value.value(QLatin1String("body"))
+ };
+}
+
+void QV4DebugClient::disconnect()
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "disconnect",
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(DISCONNECT));
+ d->sendMessage(DISCONNECT, jsonVal);
+}
+
+void QV4DebugClientPrivate::onStateChanged(QQmlDebugClient::State state)
+{
+ if (state == QQmlDebugClient::Enabled)
+ flushSendBuffer();
+}
+
+void QV4DebugClient::messageReceived(const QByteArray &data)
+{
+ Q_D(QV4DebugClient);
+ QPacket ds(connection()->currentDataStreamVersion(), data);
+ QByteArray command;
+ ds >> command;
+
+ if (command == "V8DEBUG") {
+ QByteArray type;
+ ds >> type >> d->response;
+
+ if (type == CONNECT) {
+ emit connected();
+
+ } else if (type == INTERRUPT) {
+ emit interrupted();
+
+ } else if (type == V8MESSAGE) {
+ const QJsonObject value = QJsonDocument::fromJson(d->response).object();
+ QString type = value.value(QLatin1String(TYPE)).toString();
+
+ if (type == QLatin1String("response")) {
+
+ if (!value.value(QLatin1String("success")).toBool()) {
+ emit failure();
+ qDebug() << "Received success == false response from application:"
+ << value.value(QLatin1String("message")).toString();
+ return;
+ }
+
+ QString debugCommand(value.value(QLatin1String(COMMAND)).toString());
+ if (debugCommand == QLatin1String(BACKTRACE) ||
+ debugCommand == QLatin1String(LOOKUP) ||
+ debugCommand == QLatin1String(SETBREAKPOINT) ||
+ debugCommand == QLatin1String(EVALUATE) ||
+ debugCommand == QLatin1String(VERSION) ||
+ debugCommand == QLatin1String(DISCONNECT) ||
+ debugCommand == QLatin1String(GARBAGECOLLECTOR) ||
+ debugCommand == QLatin1String(CHANGEBREAKPOINT) ||
+ debugCommand == QLatin1String(CLEARBREAKPOINT) ||
+ debugCommand == QLatin1String(FRAME) ||
+ debugCommand == QLatin1String(SCOPE) ||
+ debugCommand == QLatin1String(SCOPES) ||
+ debugCommand == QLatin1String(SCRIPTS) ||
+ debugCommand == QLatin1String(SOURCE) ||
+ debugCommand == QLatin1String(SETEXCEPTIONBREAK)) {
+ emit result();
+ } else {
+ // DO NOTHING
+ }
+
+ } else if (type == QLatin1String(EVENT)) {
+ QString event(value.value(QLatin1String(EVENT)).toString());
+
+ if (event == QLatin1String("break") || event == QLatin1String("exception"))
+ emit stopped();
+ }
+ }
+ }
+}
+
+void QV4DebugClientPrivate::sendMessage(const QByteArray &command, const QJsonObject &args)
+{
+ Q_Q(QV4DebugClient);
+ const QByteArray msg = packMessage(command, args);
+ if (q->state() == QQmlDebugClient::Enabled) {
+ q->sendMessage(msg);
+ } else {
+ sendBuffer.append(msg);
+ }
+}
+
+void QV4DebugClientPrivate::flushSendBuffer()
+{
+ foreach (const QByteArray &msg, sendBuffer)
+ sendMessage(msg);
+ sendBuffer.clear();
+}
+
+QByteArray QV4DebugClientPrivate::packMessage(const QByteArray &type, const QJsonObject &object)
+{
+ QPacket rs(connection->currentDataStreamVersion());
+ QByteArray cmd = "V8DEBUG";
+ rs << cmd << type << QJsonDocument(object).toJson(QJsonDocument::Compact);
+ return rs.data();
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qv4debugclient_p.h b/src/qmldebug/qv4debugclient_p.h
new file mode 100644
index 0000000000..fdcf4284c5
--- /dev/null
+++ b/src/qmldebug/qv4debugclient_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4DEBUGCLIENT_P_H
+#define QV4DEBUGCLIENT_P_H
+
+#include <QtQmlDebug/private/qqmldebugclient_p.h>
+#include <QtCore/qjsonvalue.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QV4DebugClientPrivate;
+class QV4DebugClient : public QQmlDebugClient
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QV4DebugClient)
+
+public:
+ enum StepAction
+ {
+ Continue,
+ In,
+ Out,
+ Next
+ };
+
+ enum Exception
+ {
+ All,
+ Uncaught
+ };
+
+ struct Response
+ {
+ QString command;
+ QJsonValue body;
+ };
+
+ QV4DebugClient(QQmlDebugConnection *connection);
+
+ void connect();
+ void disconnect();
+
+ void interrupt();
+ void continueDebugging(StepAction stepAction);
+ void evaluate(const QString &expr, int frame = -1, int context = -1);
+ void lookup(const QList<int> &handles, bool includeSource = false);
+ void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false);
+ void frame(int number = -1);
+ void scope(int number = -1, int frameNumber = -1);
+ void scripts(int types = 4, const QList<int> &ids = QList<int>(), bool includeSource = false);
+ void setBreakpoint(const QString &target, int line = -1, int column = -1, bool enabled = true,
+ const QString &condition = QString(), int ignoreCount = -1);
+ void clearBreakpoint(int breakpoint);
+ void changeBreakpoint(int breakpoint, bool enabled);
+ void setExceptionBreak(Exception type, bool enabled = false);
+ void version();
+
+ Response response() const;
+
+protected:
+ void messageReceived(const QByteArray &data) override;
+
+signals:
+ void connected();
+ void interrupted();
+ void result();
+ void failure();
+ void stopped();
+};
+
+QT_END_NAMESPACE
+
+#endif // QV4DEBUGCLIENT_P_H
diff --git a/src/qmldebug/qv4debugclient_p_p.h b/src/qmldebug/qv4debugclient_p_p.h
new file mode 100644
index 0000000000..993c281632
--- /dev/null
+++ b/src/qmldebug/qv4debugclient_p_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4DEBUGCLIENT_P_P_H
+#define QV4DEBUGCLIENT_P_P_H
+
+#include "qv4debugclient_p.h"
+#include "qqmldebugclient_p_p.h"
+
+#include <QtCore/qjsonobject.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QV4DebugClientPrivate : public QQmlDebugClientPrivate
+{
+ Q_DECLARE_PUBLIC(QV4DebugClient)
+
+public:
+ QV4DebugClientPrivate(QQmlDebugConnection *connection);
+
+ void sendMessage(const QByteArray &command, const QJsonObject &args = QJsonObject());
+ void flushSendBuffer();
+ QByteArray packMessage(const QByteArray &type, const QJsonObject &object);
+ void onStateChanged(QQmlDebugClient::State state);
+
+ int seq = 0;
+ QList<QByteArray> sendBuffer;
+ QByteArray response;
+};
+
+QT_END_NAMESPACE
+
+#endif // QV4DEBUGCLIENT_P_P_H
diff --git a/src/qmldevtools/qmldevtools.pro b/src/qmldevtools/qmldevtools.pro
index 05aa6f66f5..45029400b9 100644
--- a/src/qmldevtools/qmldevtools.pro
+++ b/src/qmldevtools/qmldevtools.pro
@@ -17,5 +17,6 @@ include(../qml/parser/parser.pri)
include(../qml/jsruntime/jsruntime.pri)
include(../qml/compiler/compiler.pri)
include(../qml/memory/memory.pri)
+include(../qml/qmldirparser/qmldirparser.pri)
load(qt_module)
diff --git a/src/qmltest/qmltest.pro b/src/qmltest/qmltest.pro
index e2200e5abb..0bf05093be 100644
--- a/src/qmltest/qmltest.pro
+++ b/src/qmltest/qmltest.pro
@@ -4,7 +4,7 @@ QMAKE_DOCS = $$PWD/doc/qtqmltest.qdocconf
DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_FOREACH
QT = core testlib-private
-QT_PRIVATE = quick qml-private gui core-private gui-private
+QT_PRIVATE = quick quick-private qml-private gui core-private gui-private
# Testlib is only a private dependency, which results in our users not
# inheriting testlibs's MODULE_CONFIG transitively. Make it explicit.
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index f666bc2284..8803075284 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -44,10 +44,14 @@
#include <QtQml/qqml.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcontext.h>
+#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
#include <QtQml/qjsvalue.h>
#include <QtQml/qjsengine.h>
#include <QtQml/qqmlpropertymap.h>
+#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/qquickitem.h>
#include <QtGui/qopengl.h>
#include <QtCore/qurl.h>
#include <QtCore/qfileinfo.h>
@@ -72,6 +76,65 @@
QT_BEGIN_NAMESPACE
+/*!
+ \fn bool qIsPolishScheduled(const QQuickItem *item)
+ \relates QtQuickTest
+ \since 5.13
+
+ Returns \c true if \l {QQuickItem::}{updatePolish()} has not been called
+ on \a item since the last call to \l {QQuickItem::}{polish()},
+ otherwise returns \c false.
+
+ When assigning values to properties in QML, any layouting the item
+ must do as a result of the assignment might not take effect immediately,
+ but can instead be postponed until the item is polished. For these cases,
+ you can use this function to ensure that the item has been polished
+ before the execution of the test continues. For example:
+
+ \code
+ QVERIFY(QQuickTest::qIsPolishScheduled(item));
+ QVERIFY(QQuickTest::qWaitForItemPolished(item));
+ \endcode
+
+ Without the call to \c qIsPolishScheduled() above, the
+ call to \c qWaitForItemPolished() might see that no polish
+ was scheduled and therefore pass instantly, assuming that
+ the item had already been polished. This function
+ makes it obvious why an item wasn't polished and allows tests to
+ fail early under such circumstances.
+
+ \sa QQuickItem::polish(), QQuickItem::updatePolish()
+*/
+bool QQuickTest::qIsPolishScheduled(const QQuickItem *item)
+{
+ return QQuickItemPrivate::get(item)->polishScheduled;
+}
+
+/*!
+ \fn bool qWaitForItemPolished(const QQuickItem *item, int timeout = 5000)
+ \relates QtQuickTest
+ \since 5.13
+
+ Waits for \a timeout milliseconds or until
+ \l {QQuickItem::}{updatePolish()} has been called on \a item.
+
+ Returns \c true if \c updatePolish() was called on \a item within
+ \a timeout milliseconds, otherwise returns \c false.
+
+ To use this function, add the following line to your test's \c .pro file:
+
+ \code
+ QT += qmltest
+ \endcode
+
+ \sa QQuickItem::polish(), QQuickItem::updatePolish(),
+ QQuickTest::qIsPolishScheduled()
+*/
+bool QQuickTest::qWaitForItemPolished(const QQuickItem *item, int timeout)
+{
+ return QTest::qWaitFor([&]() { return !QQuickItemPrivate::get(item)->polishScheduled; }, timeout);
+}
+
class QTestRootObject : public QObject
{
Q_OBJECT
@@ -198,6 +261,21 @@ bool qWaitForSignal(QObject *obj, const char* signal, int timeout = 5000)
return spy.size();
}
+void maybeInvokeSetupMethod(QObject *setupObject, const char *member, QGenericArgument val0 = QGenericArgument(nullptr))
+{
+ // It's OK if it doesn't exist: since we have more than one callback that
+ // can be called, it makes sense if the user only implements one of them.
+ // We do this the long way rather than just calling the static
+ // QMetaObject::invokeMethod(), because that will issue a warning if the
+ // function doesn't exist, which we don't want.
+ const QMetaObject *setupMetaObject = setupObject->metaObject();
+ const int methodIndex = setupMetaObject->indexOfMethod(member);
+ if (methodIndex != -1) {
+ const QMetaMethod method = setupMetaObject->method(methodIndex);
+ method.invoke(setupObject, val0);
+ }
+}
+
using namespace QV4::CompiledData;
class TestCaseCollector
@@ -359,10 +437,8 @@ int quick_test_main_with_setup(int argc, char **argv, const char *name, const ch
}
}
- if (setup) {
- // Don't check the return value; it's OK if it doesn't exist.
- QMetaObject::invokeMethod(setup, "applicationAvailable");
- }
+ if (setup)
+ maybeInvokeSetupMethod(setup, "applicationAvailable()");
// Look for QML-specific command-line options.
// -import dir Specify an import directory.
@@ -535,11 +611,8 @@ int quick_test_main_with_setup(int argc, char **argv, const char *name, const ch
// Do this down here so that import paths, plugin paths,
// file selectors, etc. are available in case the user needs access to them.
- if (setup) {
- // Don't check the return value; it's OK if it doesn't exist.
- // If we add more callbacks in the future, it makes sense if the user only implements one of them.
- QMetaObject::invokeMethod(setup, "qmlEngineAvailable", Q_ARG(QQmlEngine*, view.engine()));
- }
+ if (setup)
+ maybeInvokeSetupMethod(setup, "qmlEngineAvailable(QQmlEngine*)", Q_ARG(QQmlEngine*, view.engine()));
view.setObjectName(fi.baseName());
view.setTitle(view.objectName());
@@ -588,10 +661,8 @@ int quick_test_main_with_setup(int argc, char **argv, const char *name, const ch
}
}
- if (setup) {
- // Don't check the return value; it's OK if it doesn't exist.
- QMetaObject::invokeMethod(setup, "cleanupTestCase");
- }
+ if (setup)
+ maybeInvokeSetupMethod(setup, "cleanupTestCase()");
// Flush the current logging stream.
QuickTestResult::setProgramName(nullptr);
diff --git a/src/qmltest/quicktest.h b/src/qmltest/quicktest.h
index 62ed749722..8e3510c9a5 100644
--- a/src/qmltest/quicktest.h
+++ b/src/qmltest/quicktest.h
@@ -45,7 +45,7 @@
QT_BEGIN_NAMESPACE
-QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS
+class QQuickItem;
Q_QUICK_TEST_EXPORT int quick_test_main(int argc, char **argv, const char *name, const char *sourceDir);
Q_QUICK_TEST_EXPORT int quick_test_main_with_setup(int argc, char **argv, const char *name, const char *sourceDir, QObject *setup);
@@ -55,7 +55,6 @@ Q_QUICK_TEST_EXPORT int quick_test_main_with_setup(int argc, char **argv, const
#define QUICK_TEST_MAIN(name) \
int main(int argc, char **argv) \
{ \
- QTEST_ADD_GPU_BLACKLIST_SUPPORT \
QTEST_SET_MAIN_SOURCE_PATH \
return quick_test_main(argc, argv, #name, QUICK_TEST_SOURCE_DIR); \
}
@@ -63,7 +62,6 @@ Q_QUICK_TEST_EXPORT int quick_test_main_with_setup(int argc, char **argv, const
#define QUICK_TEST_OPENGL_MAIN(name) \
int main(int argc, char **argv) \
{ \
- QTEST_ADD_GPU_BLACKLIST_SUPPORT \
QTEST_SET_MAIN_SOURCE_PATH \
return quick_test_main(argc, argv, #name, QUICK_TEST_SOURCE_DIR); \
}
@@ -71,7 +69,6 @@ Q_QUICK_TEST_EXPORT int quick_test_main_with_setup(int argc, char **argv, const
#define QUICK_TEST_MAIN_WITH_SETUP(name, QuickTestSetupClass) \
int main(int argc, char **argv) \
{ \
- QTEST_ADD_GPU_BLACKLIST_SUPPORT \
QTEST_SET_MAIN_SOURCE_PATH \
QuickTestSetupClass setup; \
return quick_test_main_with_setup(argc, argv, #name, QUICK_TEST_SOURCE_DIR, &setup); \
@@ -82,7 +79,6 @@ Q_QUICK_TEST_EXPORT int quick_test_main_with_setup(int argc, char **argv, const
#define QUICK_TEST_MAIN(name) \
int main(int argc, char **argv) \
{ \
- QTEST_ADD_GPU_BLACKLIST_SUPPORT \
QTEST_SET_MAIN_SOURCE_PATH \
return quick_test_main(argc, argv, #name, nullptr); \
}
@@ -90,7 +86,6 @@ Q_QUICK_TEST_EXPORT int quick_test_main_with_setup(int argc, char **argv, const
#define QUICK_TEST_OPENGL_MAIN(name) \
int main(int argc, char **argv) \
{ \
- QTEST_ADD_GPU_BLACKLIST_SUPPORT \
QTEST_SET_MAIN_SOURCE_PATH \
return quick_test_main(argc, argv, #name, nullptr); \
}
@@ -98,7 +93,6 @@ Q_QUICK_TEST_EXPORT int quick_test_main_with_setup(int argc, char **argv, const
#define QUICK_TEST_MAIN_WITH_SETUP(name, QuickTestSetupClass) \
int main(int argc, char **argv) \
{ \
- QTEST_ADD_GPU_BLACKLIST_SUPPORT \
QTEST_SET_MAIN_SOURCE_PATH \
QuickTestSetupClass setup; \
return quick_test_main_with_setup(argc, argv, #name, nullptr, &setup); \
@@ -106,6 +100,11 @@ Q_QUICK_TEST_EXPORT int quick_test_main_with_setup(int argc, char **argv, const
#endif
+namespace QQuickTest {
+Q_QUICK_TEST_EXPORT bool qIsPolishScheduled(const QQuickItem *item);
+Q_QUICK_TEST_EXPORT bool qWaitForItemPolished(const QQuickItem *item, int timeout = 5000);
+}
+
QT_END_NAMESPACE
#endif
diff --git a/src/qmltest/quicktestresult.cpp b/src/qmltest/quicktestresult.cpp
index 3225dc95cd..4dbec585c4 100644
--- a/src/qmltest/quicktestresult.cpp
+++ b/src/qmltest/quicktestresult.cpp
@@ -39,6 +39,7 @@
****************************************************************************/
#include "quicktestresult_p.h"
+#include "quicktest.h"
#include <QtTest/qtestcase.h>
#include <QtTest/qtestsystem.h>
#include <QtTest/private/qtestblacklist_p.h>
@@ -787,6 +788,16 @@ QObject *QuickTestResult::findChild(QObject *parent, const QString &objectName)
return parent ? parent->findChild<QObject*>(objectName) : 0;
}
+bool QuickTestResult::isPolishScheduled(QQuickItem *item) const
+{
+ return QQuickTest::qIsPolishScheduled(item);
+}
+
+bool QuickTestResult::waitForItemPolished(QQuickItem *item, int timeout)
+{
+ return QQuickTest::qWaitForItemPolished(item, timeout);
+}
+
namespace QTest {
void qtest_qParseArgs(int argc, char *argv[], bool qml);
};
@@ -802,7 +813,6 @@ void QuickTestResult::setProgramName(const char *name)
{
if (name) {
QTestPrivate::parseBlackList();
- QTestPrivate::parseGpuBlackList();
QTestResult::reset();
} else if (!name && loggingStarted) {
QTestResult::setCurrentTestObject(globalProgramName);
@@ -829,7 +839,7 @@ int QuickTestResult::exitCode()
#endif
}
+QT_END_NAMESPACE
+
#include "quicktestresult.moc"
#include "moc_quicktestresult_p.cpp"
-
-QT_END_NAMESPACE
diff --git a/src/qmltest/quicktestresult_p.h b/src/qmltest/quicktestresult_p.h
index b2eeefdfff..0659919a39 100644
--- a/src/qmltest/quicktestresult_p.h
+++ b/src/qmltest/quicktestresult_p.h
@@ -160,6 +160,9 @@ public Q_SLOTS:
Q_REVISION(1) QObject *findChild(QObject *parent, const QString &objectName);
+ bool isPolishScheduled(QQuickItem *item) const;
+ bool waitForItemPolished(QQuickItem *item, int timeout);
+
public:
// Helper functions for the C++ main() shell.
static void parseArgs(int argc, char *argv[]);
diff --git a/src/quick/accessible/qaccessiblequickview.cpp b/src/quick/accessible/qaccessiblequickview.cpp
index 3bb40546be..41a02fc09c 100644
--- a/src/quick/accessible/qaccessiblequickview.cpp
+++ b/src/quick/accessible/qaccessiblequickview.cpp
@@ -91,7 +91,7 @@ QAccessibleInterface *QAccessibleQuickWindow::focusChild() const
QAccessible::Role QAccessibleQuickWindow::role() const
{
- return QAccessible::Window; // FIXME
+ return QAccessible::Window;
}
QAccessible::State QAccessibleQuickWindow::state() const
diff --git a/src/quick/designer/qquickdesignersupportitems.cpp b/src/quick/designer/qquickdesignersupportitems.cpp
index 1c338fa79d..ed5fdf3a4a 100644
--- a/src/quick/designer/qquickdesignersupportitems.cpp
+++ b/src/quick/designer/qquickdesignersupportitems.cpp
@@ -192,19 +192,19 @@ static bool isCrashingType(const QQmlType &type)
{
QString name = type.qmlTypeName();
- if (type.qmlTypeName() == QLatin1String("QtMultimedia/MediaPlayer"))
+ if (name == QLatin1String("QtMultimedia/MediaPlayer"))
return true;
- if (type.qmlTypeName() == QLatin1String("QtMultimedia/Audio"))
+ if (name == QLatin1String("QtMultimedia/Audio"))
return true;
- if (type.qmlTypeName() == QLatin1String("QtQuick.Controls/MenuItem"))
+ if (name == QLatin1String("QtQuick.Controls/MenuItem"))
return true;
- if (type.qmlTypeName() == QLatin1String("QtQuick.Controls/Menu"))
+ if (name == QLatin1String("QtQuick.Controls/Menu"))
return true;
- if (type.qmlTypeName() == QLatin1String("QtQuick/Timer"))
+ if (name == QLatin1String("QtQuick/Timer"))
return true;
return false;
diff --git a/src/quick/handlers/handlers.pri b/src/quick/handlers/handlers.pri
index 1258822f40..226cca22cb 100644
--- a/src/quick/handlers/handlers.pri
+++ b/src/quick/handlers/handlers.pri
@@ -10,6 +10,7 @@ HEADERS += \
$$PWD/qquickpointerhandler_p_p.h \
$$PWD/qquickpointhandler_p.h \
$$PWD/qquicksinglepointhandler_p.h \
+ $$PWD/qquicksinglepointhandler_p_p.h \
$$PWD/qquicktaphandler_p.h \
$$PWD/qquickdragaxis_p.h
diff --git a/src/quick/handlers/qquicksinglepointhandler.cpp b/src/quick/handlers/qquicksinglepointhandler.cpp
index 82e5b1b05d..8f2f403975 100644
--- a/src/quick/handlers/qquicksinglepointhandler.cpp
+++ b/src/quick/handlers/qquicksinglepointhandler.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qquicksinglepointhandler_p.h"
+#include "qquicksinglepointhandler_p_p.h"
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(DBG_TOUCH_TARGET)
@@ -59,19 +60,25 @@ Q_DECLARE_LOGGING_CATEGORY(DBG_TOUCH_TARGET)
*/
QQuickSinglePointHandler::QQuickSinglePointHandler(QQuickItem *parent)
- : QQuickPointerDeviceHandler(parent)
+ : QQuickPointerDeviceHandler(*(new QQuickSinglePointHandlerPrivate), parent)
+{
+}
+
+QQuickSinglePointHandler::QQuickSinglePointHandler(QQuickSinglePointHandlerPrivate &dd, QQuickItem *parent)
+ : QQuickPointerDeviceHandler(dd, parent)
{
}
bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event)
{
+ Q_D(QQuickSinglePointHandler);
if (!QQuickPointerDeviceHandler::wantsPointerEvent(event))
return false;
if (event->device()->pointerType() != QQuickPointerDevice::Finger &&
(event->buttons() & acceptedButtons()) == 0 && (event->button() & acceptedButtons()) == 0)
return false;
- if (m_pointInfo.m_id) {
+ if (d->pointInfo.id()) {
// We already know which one we want, so check whether it's there.
// It's expected to be an update or a release.
// If we no longer want it, cancel the grab.
@@ -81,7 +88,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event)
int c = event->pointCount();
for (int i = 0; i < c; ++i) {
QQuickEventPoint *p = event->point(i);
- const bool found = (p->pointId() == m_pointInfo.m_id);
+ const bool found = (p->pointId() == d->pointInfo.id());
if (found)
missing = false;
if (wantsEventPoint(p)) {
@@ -91,10 +98,10 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event)
}
}
if (missing)
- qCWarning(DBG_TOUCH_TARGET) << this << "pointId" << hex << m_pointInfo.m_id
+ qCWarning(DBG_TOUCH_TARGET) << this << "pointId" << hex << d->pointInfo.id()
<< "is missing from current event, but was neither canceled nor released";
if (point) {
- if (candidatePointCount == 1 || (candidatePointCount > 1 && m_ignoreAdditionalPoints)) {
+ if (candidatePointCount == 1 || (candidatePointCount > 1 && d->ignoreAdditionalPoints)) {
point->setAccepted();
return true;
} else {
@@ -121,35 +128,37 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event)
chosen->setAccepted();
}
}
- return m_pointInfo.m_id;
+ return d->pointInfo.id();
}
void QQuickSinglePointHandler::handlePointerEventImpl(QQuickPointerEvent *event)
{
+ Q_D(QQuickSinglePointHandler);
QQuickPointerDeviceHandler::handlePointerEventImpl(event);
- QQuickEventPoint *currentPoint = event->pointById(m_pointInfo.m_id);
+ QQuickEventPoint *currentPoint = event->pointById(d->pointInfo.id());
Q_ASSERT(currentPoint);
- m_pointInfo.reset(currentPoint);
+ d->pointInfo.reset(currentPoint);
handleEventPoint(currentPoint);
if (currentPoint->state() == QQuickEventPoint::Released && (event->buttons() & acceptedButtons()) == Qt::NoButton) {
setExclusiveGrab(currentPoint, false);
- reset();
+ d->reset();
}
emit pointChanged();
}
void QQuickSinglePointHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point)
{
+ Q_D(QQuickSinglePointHandler);
if (grabber != this)
return;
switch (transition) {
case QQuickEventPoint::GrabExclusive:
- m_pointInfo.m_sceneGrabPosition = point->sceneGrabPosition();
+ d->pointInfo.m_sceneGrabPosition = point->sceneGrabPosition();
setActive(true);
QQuickPointerHandler::onGrabChanged(grabber, transition, point);
break;
case QQuickEventPoint::GrabPassive:
- m_pointInfo.m_sceneGrabPosition = point->sceneGrabPosition();
+ d->pointInfo.m_sceneGrabPosition = point->sceneGrabPosition();
QQuickPointerHandler::onGrabChanged(grabber, transition, point);
break;
case QQuickEventPoint::OverrideGrabPassive:
@@ -160,32 +169,35 @@ void QQuickSinglePointHandler::onGrabChanged(QQuickPointerHandler *grabber, QQui
case QQuickEventPoint::CancelGrabExclusive:
// the grab is lost or relinquished, so the point is no longer relevant
QQuickPointerHandler::onGrabChanged(grabber, transition, point);
- reset();
+ d->reset();
break;
}
}
void QQuickSinglePointHandler::setIgnoreAdditionalPoints(bool v)
{
- m_ignoreAdditionalPoints = v;
+ Q_D(QQuickSinglePointHandler);
+ d->ignoreAdditionalPoints = v;
}
void QQuickSinglePointHandler::moveTarget(QPointF pos, QQuickEventPoint *point)
{
+ Q_D(QQuickSinglePointHandler);
target()->setPosition(pos);
- m_pointInfo.m_scenePosition = point->scenePosition();
- m_pointInfo.m_position = target()->mapFromScene(m_pointInfo.m_scenePosition);
+ d->pointInfo.m_scenePosition = point->scenePosition();
+ d->pointInfo.m_position = target()->mapFromScene(d->pointInfo.m_scenePosition);
}
void QQuickSinglePointHandler::setPointId(int id)
{
- m_pointInfo.m_id = id;
+ Q_D(QQuickSinglePointHandler);
+ d->pointInfo.m_id = id;
}
-void QQuickSinglePointHandler::reset()
+QQuickHandlerPoint QQuickSinglePointHandler::point() const
{
- setActive(false);
- m_pointInfo.reset();
+ Q_D(const QQuickSinglePointHandler);
+ return d->pointInfo;
}
/*!
@@ -196,4 +208,16 @@ void QQuickSinglePointHandler::reset()
handled, this object is reset to default values (all coordinates are 0).
*/
+QQuickSinglePointHandlerPrivate::QQuickSinglePointHandlerPrivate()
+ : QQuickPointerDeviceHandlerPrivate()
+{
+}
+
+void QQuickSinglePointHandlerPrivate::reset()
+{
+ Q_Q(QQuickSinglePointHandler);
+ q->setActive(false);
+ pointInfo.reset();
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/handlers/qquicksinglepointhandler_p.h b/src/quick/handlers/qquicksinglepointhandler_p.h
index b9e5b12224..edc55aaaf6 100644
--- a/src/quick/handlers/qquicksinglepointhandler_p.h
+++ b/src/quick/handlers/qquicksinglepointhandler_p.h
@@ -56,24 +56,29 @@
QT_BEGIN_NAMESPACE
+class QQuickSinglePointHandlerPrivate;
+
class Q_QUICK_PRIVATE_EXPORT QQuickSinglePointHandler : public QQuickPointerDeviceHandler
{
Q_OBJECT
Q_PROPERTY(QQuickHandlerPoint point READ point NOTIFY pointChanged)
+
public:
explicit QQuickSinglePointHandler(QQuickItem *parent = nullptr);
- QQuickHandlerPoint point() const { return m_pointInfo; }
+ QQuickHandlerPoint point() const;
Q_SIGNALS:
void pointChanged();
protected:
+ QQuickSinglePointHandler(QQuickSinglePointHandlerPrivate &dd, QQuickItem *parent);
+
bool wantsPointerEvent(QQuickPointerEvent *event) override;
void handlePointerEventImpl(QQuickPointerEvent *event) override;
virtual void handleEventPoint(QQuickEventPoint *point) = 0;
- QQuickEventPoint *currentPoint(QQuickPointerEvent *ev) { return ev->pointById(m_pointInfo.m_id); }
+ QQuickEventPoint *currentPoint(QQuickPointerEvent *ev);
void onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point) override;
void setIgnoreAdditionalPoints(bool v = true);
@@ -82,12 +87,7 @@ protected:
void setPointId(int id);
-private:
- void reset();
-
-private:
- QQuickHandlerPoint m_pointInfo;
- bool m_ignoreAdditionalPoints = false;
+ Q_DECLARE_PRIVATE(QQuickSinglePointHandler)
};
QT_END_NAMESPACE
diff --git a/src/quick/handlers/qquicksinglepointhandler_p_p.h b/src/quick/handlers/qquicksinglepointhandler_p_p.h
new file mode 100644
index 0000000000..1e66c25e14
--- /dev/null
+++ b/src/quick/handlers/qquicksinglepointhandler_p_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKPOINTERSINGLEHANDLER_P_H
+#define QQUICKPOINTERSINGLEHANDLER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickhandlerpoint_p.h"
+#include "qquickpointerdevicehandler_p_p.h"
+#include "qquicksinglepointhandler_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_PRIVATE_EXPORT QQuickSinglePointHandlerPrivate : public QQuickPointerDeviceHandlerPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickSinglePointHandler)
+
+public:
+ static QQuickSinglePointHandlerPrivate* get(QQuickSinglePointHandler *q) { return q->d_func(); }
+ static const QQuickSinglePointHandlerPrivate* get(const QQuickSinglePointHandler *q) { return q->d_func(); }
+
+ QQuickSinglePointHandlerPrivate();
+
+ void reset();
+
+ QQuickHandlerPoint pointInfo;
+ bool ignoreAdditionalPoints = false;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKPOINTERSINGLEHANDLER_P_H
+
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index 06dddabb65..14443a2f2f 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -735,7 +735,7 @@ void QQuickCanvasItem::updatePolish()
for (auto it = animationCallbacks.cbegin(), end = animationCallbacks.cend(); it != end; ++it) {
function = it.value().value();
- jsCall->args[0] = QV4::Value::fromUInt32(QDateTime::currentMSecsSinceEpoch() / 1000);
+ jsCall->args[0] = QV4::Value::fromUInt32(QDateTime::currentMSecsSinceEpoch());
function->call(jsCall);
}
}
diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h
index b7c4fa5b67..7e9b18e101 100644
--- a/src/quick/items/qquickflickable_p.h
+++ b/src/quick/items/qquickflickable_p.h
@@ -117,7 +117,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickFlickable : public QQuickItem
public:
QQuickFlickable(QQuickItem *parent=nullptr);
- ~QQuickFlickable();
+ ~QQuickFlickable() override;
QQmlListProperty<QObject> flickableData();
QQmlListProperty<QQuickItem> flickableChildren();
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index fabd3ef03b..0cd4c446d9 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -4444,6 +4444,8 @@ void QQuickItem::update()
When the scene graph processes the request, it will call updatePolish()
on this item.
+
+ \sa updatePolish(), QQuickTest::qIsPolishScheduled()
*/
void QQuickItem::polish()
{
diff --git a/src/quick/items/qquickitemviewfxitem.cpp b/src/quick/items/qquickitemviewfxitem.cpp
index f9c65967ea..60e9d7b115 100644
--- a/src/quick/items/qquickitemviewfxitem.cpp
+++ b/src/quick/items/qquickitemviewfxitem.cpp
@@ -45,9 +45,9 @@ QT_BEGIN_NAMESPACE
QQuickItemViewFxItem::QQuickItemViewFxItem(QQuickItem *item, bool ownItem, QQuickItemChangeListener* changeListener)
: item(item)
- , ownItem(ownItem)
, changeListener(changeListener)
, transitionableItem(nullptr)
+ , ownItem(ownItem)
, releaseAfterTransition(false)
, trackGeom(false)
{
diff --git a/src/quick/items/qquickitemviewfxitem_p_p.h b/src/quick/items/qquickitemviewfxitem_p_p.h
index 48ffe248bc..3bc5ba440c 100644
--- a/src/quick/items/qquickitemviewfxitem_p_p.h
+++ b/src/quick/items/qquickitemviewfxitem_p_p.h
@@ -94,13 +94,13 @@ public:
virtual bool contains(qreal x, qreal y) const = 0;
- int index = -1;
QPointer<QQuickItem> item;
- bool ownItem;
QQuickItemChangeListener *changeListener;
QQuickItemViewTransitionableItem *transitionableItem;
- bool releaseAfterTransition;
- bool trackGeom;
+ int index = -1;
+ bool ownItem : 1;
+ bool releaseAfterTransition : 1;
+ bool trackGeom : 1;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickopenglshadereffect.cpp b/src/quick/items/qquickopenglshadereffect.cpp
index cad598d2c0..3aa00340b2 100644
--- a/src/quick/items/qquickopenglshadereffect.cpp
+++ b/src/quick/items/qquickopenglshadereffect.cpp
@@ -245,7 +245,11 @@ void QQuickOpenGLShaderEffectCommon::connectPropertySignals(QQuickItem *item,
const QMetaObject *itemMetaObject,
Key::ShaderType shaderType)
{
- QQmlPropertyCache *propCache = QQmlData::ensurePropertyCache(qmlEngine(item), item);
+ auto engine = qmlEngine(item);
+ if (!engine)
+ return;
+
+ QQmlPropertyCache *propCache = QQmlData::ensurePropertyCache(engine, item);
for (int i = 0; i < uniformData[shaderType].size(); ++i) {
if (signalMappers[shaderType].at(i) == 0)
continue;
@@ -317,7 +321,8 @@ void QQuickOpenGLShaderEffectCommon::lookThroughShaderCode(QQuickItem *item,
Key::ShaderType shaderType,
const QByteArray &code)
{
- QQmlPropertyCache *propCache = QQmlData::ensurePropertyCache(qmlEngine(item), item);
+ auto engine = qmlEngine(item);
+ QQmlPropertyCache *propCache = (engine) ? QQmlData::ensurePropertyCache(engine, item) : nullptr;
int index = 0;
int typeIndex = -1;
int typeLength = 0;
@@ -350,9 +355,11 @@ void QQuickOpenGLShaderEffectCommon::lookThroughShaderCode(QQuickItem *item,
} else if (nameLength > srLen && qstrncmp("qt_SubRect_", s + nameIndex, srLen) == 0) {
d.specialType = UniformData::SubRect;
} else {
- if (QQmlPropertyData *pd = propCache->property(QString::fromUtf8(d.name), nullptr, nullptr)) {
- if (!pd->isFunction())
- d.propertyIndex = pd->coreIndex();
+ if (propCache) {
+ if (QQmlPropertyData *pd = propCache->property(QString::fromUtf8(d.name), nullptr, nullptr)) {
+ if (!pd->isFunction())
+ d.propertyIndex = pd->coreIndex();
+ }
}
const int mappedId = uniformData[shaderType].size() | (shaderType << 16);
mapper = new QtPrivate::MappedSlotObject([this, mappedId](){
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index eaf0e4cf89..b1900c5b7a 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -1774,6 +1774,16 @@ QQuickTableView::QQuickTableView(QQuickItem *parent)
setFlag(QQuickItem::ItemIsFocusScope);
}
+QQuickTableView::~QQuickTableView()
+{
+}
+
+QQuickTableView::QQuickTableView(QQuickTableViewPrivate &dd, QQuickItem *parent)
+ : QQuickFlickable(dd, parent)
+{
+ setFlag(QQuickItem::ItemIsFocusScope);
+}
+
int QQuickTableView::rows() const
{
return d_func()->tableSize.height();
diff --git a/src/quick/items/qquicktableview_p.h b/src/quick/items/qquicktableview_p.h
index 9fcd4c6c17..c5197b4230 100644
--- a/src/quick/items/qquicktableview_p.h
+++ b/src/quick/items/qquicktableview_p.h
@@ -82,7 +82,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTableView : public QQuickFlickable
public:
QQuickTableView(QQuickItem *parent = nullptr);
-
+ ~QQuickTableView() override;
int rows() const;
int columns() const;
@@ -98,8 +98,8 @@ public:
QJSValue columnWidthProvider() const;
void setColumnWidthProvider(QJSValue provider);
- QVariant model() const;
- void setModel(const QVariant &newModel);
+ virtual QVariant model() const;
+ virtual void setModel(const QVariant &newModel);
QQmlComponent *delegate() const;
void setDelegate(QQmlComponent *);
@@ -130,6 +130,9 @@ protected:
void viewportMoved(Qt::Orientations orientation) override;
void componentComplete() override;
+protected:
+ QQuickTableView(QQuickTableViewPrivate &dd, QQuickItem *parent);
+
private:
Q_DISABLE_COPY(QQuickTableView)
Q_DECLARE_PRIVATE(QQuickTableView)
diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp
index 504d629b3e..792aa31a88 100644
--- a/src/quick/items/qquicktextnodeengine.cpp
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -1051,7 +1051,7 @@ void QQuickTextNodeEngine::addTextBlock(QTextDocument *textDocument, const QText
if (text.contains(QChar::ObjectReplacementCharacter)) {
QTextFrame *frame = qobject_cast<QTextFrame *>(textDocument->objectForFormat(charFormat));
- if (frame && frame->frameFormat().position() == QTextFrameFormat::InFlow) {
+ if (!frame || frame->frameFormat().position() == QTextFrameFormat::InFlow) {
int blockRelativePosition = textPos - block.position();
QTextLine line = block.layout()->lineForTextPosition(blockRelativePosition);
if (!currentLine().isValid()
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index dd5960e925..b5a68a2283 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -4608,6 +4608,62 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
+ \qmlproperty QWindow Window::transientParent
+ \since 5.13
+
+ The window for which this window is a transient pop-up.
+
+ This is a hint to the window manager that this window is a dialog or pop-up
+ on behalf of the transient parent. It usually means that the transient
+ window will be centered over its transient parent when it is initially
+ shown, that minimizing the parent window will also minimize the transient
+ window, and so on; however results vary somewhat from platform to platform.
+
+ Normally if you declare a Window inside an Item or inside another Window,
+ this relationship is deduced automatically. In that case, if you declare
+ this window's \l visible property \c true, it will not actually be shown
+ until the \c transientParent window is shown.
+
+ However if you set this property, then Qt Quick will no longer wait until
+ the \c transientParent window is shown before showing this window. If you
+ want to to be able to show a transient window independently of the "parent"
+ Item or Window within which it was declared, you can remove that
+ relationship by setting \c transientParent to \c null:
+
+ \l qml
+ import QtQuick.Window 2.13
+
+ Window {
+ // visible is false by default
+ Window {
+ transientParent: null
+ visible: true
+ }
+ }
+ \qml
+
+ In order to cause the window to be centered above its transient parent by
+ default, depending on the window manager, it may also be necessary to set
+ the \l Window::flags property with a suitable \l Qt::WindowType (such as
+ \c Qt::Dialog).
+*/
+
+/*!
+ \property QQuickWindow::transientParent
+ \brief The window for which this window is a transient pop-up.
+ \since 5.13
+
+ This is a hint to the window manager that this window is a dialog or pop-up
+ on behalf of the transient parent, which may be any kind of \l QWindow.
+
+ In order to cause the window to be centered above its transient parent by
+ default, depending on the window manager, it may also be necessary to set
+ the \l flags property with a suitable \l Qt::WindowType (such as \c Qt::Dialog).
+
+ \sa parent()
+ */
+
+/*!
\qmlproperty Item Window::activeFocusItem
\since 5.1
diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp
index ab3f49d5b6..2b109c0897 100644
--- a/src/quick/items/qquickwindowmodule.cpp
+++ b/src/quick/items/qquickwindowmodule.cpp
@@ -124,7 +124,8 @@ void QQuickWindowQmlImpl::componentComplete()
Q_D(QQuickWindowQmlImpl);
d->complete = true;
QQuickItem *itemParent = qmlobject_cast<QQuickItem *>(QObject::parent());
- if (itemParent && !itemParent->window()) {
+ const bool transientParentAlreadySet = QQuickWindowPrivate::get(this)->transientParentPropertySet;
+ if (!transientParentAlreadySet && itemParent && !itemParent->window()) {
qCDebug(lcTransient) << "window" << title() << "has invisible Item parent" << itemParent << "transientParent"
<< transientParent() << "declared visibility" << d->visibility << "; delaying show";
connect(itemParent, &QQuickItem::windowChanged, this,
@@ -210,6 +211,9 @@ void QQuickWindowModule::defineModule()
qmlRegisterUncreatableType<QQuickScreen,1>(uri, 2, 3, "Screen", QStringLiteral("Screen can only be used via the attached property."));
qmlRegisterUncreatableType<QQuickScreenInfo,2>(uri, 2, 3, "ScreenInfo", QStringLiteral("ScreenInfo can only be used via the attached property."));
qmlRegisterUncreatableType<QQuickScreenInfo,10>(uri, 2, 10, "ScreenInfo", QStringLiteral("ScreenInfo can only be used via the attached property."));
+ qmlRegisterRevision<QWindow,13>(uri, 2, 13);
+ qmlRegisterRevision<QQuickWindow,13>(uri, 2, 13);
+ qmlRegisterType<QQuickWindowQmlImpl,13>(uri, 2, 13, "Window");
}
QT_END_NAMESPACE
diff --git a/src/quick/quick.pro b/src/quick/quick.pro
index 0f5f5abca3..37d2ad1172 100644
--- a/src/quick/quick.pro
+++ b/src/quick/quick.pro
@@ -21,7 +21,6 @@ QMAKE_DOCS = $$PWD/doc/qtquick.qdocconf
ANDROID_LIB_DEPENDENCIES = \
lib/libQt5QuickParticles.so
MODULE_PLUGIN_TYPES += \
- accessible/libqtaccessiblequick.so \
scenegraph
ANDROID_BUNDLED_FILES += \
qml \
diff --git a/src/quick/scenegraph/util/qsgimagenode.h b/src/quick/scenegraph/util/qsgimagenode.h
index 526f52b7e5..3b78f78a0e 100644
--- a/src/quick/scenegraph/util/qsgimagenode.h
+++ b/src/quick/scenegraph/util/qsgimagenode.h
@@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE
class Q_QUICK_EXPORT QSGImageNode : public QSGGeometryNode
{
public:
- ~QSGImageNode() override { }
+ ~QSGImageNode() override = default;
virtual void setRect(const QRectF &rect) = 0;
inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); }
diff --git a/src/quick/scenegraph/util/qsgninepatchnode.h b/src/quick/scenegraph/util/qsgninepatchnode.h
index e76afd3c4a..b690a50e9d 100644
--- a/src/quick/scenegraph/util/qsgninepatchnode.h
+++ b/src/quick/scenegraph/util/qsgninepatchnode.h
@@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE
class Q_QUICK_EXPORT QSGNinePatchNode : public QSGGeometryNode
{
public:
- ~QSGNinePatchNode() override { }
+ ~QSGNinePatchNode() override = default;
virtual void setTexture(QSGTexture *texture) = 0;
virtual void setBounds(const QRectF &bounds) = 0;
diff --git a/src/quick/scenegraph/util/qsgrectanglenode.h b/src/quick/scenegraph/util/qsgrectanglenode.h
index ba52b65b07..c435dc790f 100644
--- a/src/quick/scenegraph/util/qsgrectanglenode.h
+++ b/src/quick/scenegraph/util/qsgrectanglenode.h
@@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE
class Q_QUICK_EXPORT QSGRectangleNode : public QSGGeometryNode
{
public:
- ~QSGRectangleNode() override { }
+ ~QSGRectangleNode() override = default;
virtual void setRect(const QRectF &rect) = 0;
inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); }
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index 982d05691d..720f08f69b 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -49,6 +49,7 @@
# include <qopenglfunctions.h>
# include <QtGui/qopenglcontext.h>
# include <QtGui/qopenglfunctions.h>
+# include <QtGui/private/qopengltextureuploader_p.h>
# include <private/qsgdefaultrendercontext_p.h>
#endif
#include <private/qsgmaterialshader_p.h>
@@ -89,7 +90,7 @@ static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK"
QT_BEGIN_NAMESPACE
-#if QT_CONFIG(opengl)
+#if QT_CONFIG(opengl) && !defined(QT_NO_DEBUG)
inline static bool isPowerOfTwo(int x)
{
// Assumption: x >= 1
@@ -755,9 +756,7 @@ void QSGPlainTexture::bind()
// ### TODO: check for out-of-memory situations...
- QImage tmp = (m_image.format() == QImage::Format_RGB32 || m_image.format() == QImage::Format_ARGB32_Premultiplied)
- ? m_image
- : m_image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ QOpenGLTextureUploader::BindOptions options = QOpenGLTextureUploader::PremultipliedAlphaBindOption;
// Downscale the texture to fit inside the max texture limit if it is too big.
// It would be better if the image was already downscaled to the right size,
@@ -771,75 +770,19 @@ void QSGPlainTexture::bind()
max = rc->maxTextureSize();
else
funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max);
- if (tmp.width() > max || tmp.height() > max) {
- tmp = tmp.scaled(qMin(max, tmp.width()), qMin(max, tmp.height()), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
- m_texture_size = tmp.size();
- }
+
+ m_texture_size = m_texture_size.boundedTo(QSize(max, max));
// Scale to a power of two size if mipmapping is requested and the
// texture is npot and npot textures are not properly supported.
if (mipmapFiltering() != QSGTexture::None
- && (!isPowerOfTwo(m_texture_size.width()) || !isPowerOfTwo(m_texture_size.height()))
&& !funcs->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures)) {
- tmp = tmp.scaled(qNextPowerOfTwo(m_texture_size.width()), qNextPowerOfTwo(m_texture_size.height()),
- Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
- m_texture_size = tmp.size();
+ options |= QOpenGLTextureUploader::PowerOfTwoBindOption;
}
- if (tmp.width() * 4 != tmp.bytesPerLine())
- tmp = tmp.copy();
-
- qint64 convertTime = 0;
- if (profileFrames)
- convertTime = qsg_renderer_timer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare,
- QQuickProfiler::SceneGraphTexturePrepareConvert);
-
updateBindOptions(m_dirty_bind_options);
- GLenum externalFormat = GL_RGBA;
- GLenum internalFormat = GL_RGBA;
-
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
- QString *deviceName =
- static_cast<QString *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("AndroidDeviceName"));
- static bool wrongfullyReportsBgra8888Support = deviceName != 0
- && (deviceName->compare(QLatin1String("samsung SM-T211"), Qt::CaseInsensitive) == 0
- || deviceName->compare(QLatin1String("samsung SM-T210"), Qt::CaseInsensitive) == 0
- || deviceName->compare(QLatin1String("samsung SM-T215"), Qt::CaseInsensitive) == 0);
-#else
- static bool wrongfullyReportsBgra8888Support = false;
-#endif
-
- if (context->hasExtension(QByteArrayLiteral("GL_EXT_bgra"))) {
- externalFormat = GL_BGRA;
-#ifdef QT_OPENGL_ES
- internalFormat = GL_BGRA;
-#else
- if (context->isOpenGLES())
- internalFormat = GL_BGRA;
-#endif // QT_OPENGL_ES
- } else if (!wrongfullyReportsBgra8888Support
- && (context->hasExtension(QByteArrayLiteral("GL_EXT_texture_format_BGRA8888"))
- || context->hasExtension(QByteArrayLiteral("GL_IMG_texture_format_BGRA8888")))) {
- externalFormat = GL_BGRA;
- internalFormat = GL_BGRA;
-#if defined(Q_OS_DARWIN) && !defined(Q_OS_OSX)
- } else if (context->hasExtension(QByteArrayLiteral("GL_APPLE_texture_format_BGRA8888"))) {
- externalFormat = GL_BGRA;
- internalFormat = GL_RGBA;
-#endif
- } else {
- tmp = std::move(tmp).convertToFormat(QImage::Format_RGBA8888_Premultiplied);
- }
-
- qint64 swizzleTime = 0;
- if (profileFrames)
- swizzleTime = qsg_renderer_timer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare,
- QQuickProfiler::SceneGraphTexturePrepareSwizzle);
-
- funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_texture_size.width(), m_texture_size.height(), 0, externalFormat, GL_UNSIGNED_BYTE, tmp.constBits());
+ QOpenGLTextureUploader::textureImage(GL_TEXTURE_2D, m_image, options, QSize(max, max));
qint64 uploadTime = 0;
if (profileFrames)
@@ -856,15 +799,11 @@ void QSGPlainTexture::bind()
if (profileFrames) {
mipmapTime = qsg_renderer_timer.nsecsElapsed();
qCDebug(QSG_LOG_TIME_TEXTURE,
- "plain texture uploaded in: %dms (%dx%d), bind=%d, convert=%d, swizzle=%d (%s->%s), upload=%d, mipmap=%d%s",
+ "plain texture uploaded in: %dms (%dx%d), bind=%d, upload=%d, mipmap=%d%s",
int(mipmapTime / 1000000),
m_texture_size.width(), m_texture_size.height(),
int(bindTime / 1000000),
- int((convertTime - bindTime)/1000000),
- int((swizzleTime - convertTime)/1000000),
- (externalFormat == GL_BGRA ? "BGRA" : "RGBA"),
- (internalFormat == GL_BGRA ? "BGRA" : "RGBA"),
- int((uploadTime - swizzleTime)/1000000),
+ int((uploadTime - bindTime)/1000000),
int((mipmapTime - uploadTime)/1000000),
m_texture_size != m_image.size() ? " (scaled to GL_MAX_TEXTURE_SIZE)" : "");
}
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index 0dd2a88ca1..d31e112031 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -61,9 +61,7 @@
#include <QThread>
#include <QMutex>
#include <QMutexLocker>
-#include <QWaitCondition>
#include <QBuffer>
-#include <QWaitCondition>
#include <QtCore/qdebug.h>
#include <private/qobject_p.h>
#include <QQmlFile>
@@ -222,7 +220,6 @@ private:
QMutex mutex;
QQuickPixmapReaderThreadObject *threadObject;
- QWaitCondition waitCondition;
#if QT_CONFIG(qml_network)
QNetworkAccessManager *networkAccessManager();