aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/ftw/ftw.pri4
-rw-r--r--src/qml/qml/ftw/qdeferredcleanup_p.h (renamed from src/qml/qml/qqmlmemoryprofiler_p.h)45
-rw-r--r--src/qml/qml/ftw/qhashedstring.cpp23
-rw-r--r--src/qml/qml/ftw/qhashedstring_p.h39
-rw-r--r--src/qml/qml/ftw/qqmlthread.cpp6
-rw-r--r--src/qml/qml/ftw/qqmlthread_p.h24
-rw-r--r--src/qml/qml/qml.pri13
-rw-r--r--src/qml/qml/qqml.h3
-rw-r--r--src/qml/qml/qqmlabstractbinding.cpp19
-rw-r--r--src/qml/qml/qqmlabstractbinding_p.h15
-rw-r--r--src/qml/qml/qqmlaccessors.cpp105
-rw-r--r--src/qml/qml/qqmlaccessors_p.h177
-rw-r--r--src/qml/qml/qqmlapplicationengine.cpp3
-rw-r--r--src/qml/qml/qqmlbinding.cpp476
-rw-r--r--src/qml/qml/qqmlbinding_p.h35
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp20
-rw-r--r--src/qml/qml/qqmlboundsignal_p.h4
-rw-r--r--src/qml/qml/qqmlcompileddata.cpp151
-rw-r--r--src/qml/qml/qqmlcomponent.cpp74
-rw-r--r--src/qml/qml/qqmlcomponent.h9
-rw-r--r--src/qml/qml/qqmlcomponent_p.h10
-rw-r--r--src/qml/qml/qqmlcontext.cpp7
-rw-r--r--src/qml/qml/qqmlcontext_p.h2
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp3
-rw-r--r--src/qml/qml/qqmlcontextwrapper_p.h2
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp15
-rw-r--r--src/qml/qml/qqmlcustomparser_p.h6
-rw-r--r--src/qml/qml/qqmldata_p.h63
-rw-r--r--src/qml/qml/qqmldelayedcallqueue.cpp2
-rw-r--r--src/qml/qml/qqmlengine.cpp218
-rw-r--r--src/qml/qml/qqmlengine.h3
-rw-r--r--src/qml/qml/qqmlengine_p.h13
-rw-r--r--src/qml/qml/qqmlerror.cpp4
-rw-r--r--src/qml/qml/qqmlexpression.cpp11
-rw-r--r--src/qml/qml/qqmlexpression_p.h7
-rw-r--r--src/qml/qml/qqmlextensionplugin.h2
-rw-r--r--src/qml/qml/qqmlfileselector_p.h2
-rw-r--r--src/qml/qml/qqmlimport.cpp131
-rw-r--r--src/qml/qml/qqmlincubator.cpp36
-rw-r--r--src/qml/qml/qqmlincubator_p.h4
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp81
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h26
-rw-r--r--src/qml/qml/qqmllist.cpp6
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp2
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h2
-rw-r--r--src/qml/qml/qqmlloggingcategory.cpp128
-rw-r--r--src/qml/qml/qqmlloggingcategory_p.h (renamed from src/qml/qml/ftw/qdeletewatcher_p.h)74
-rw-r--r--src/qml/qml/qqmlmemoryprofiler.cpp157
-rw-r--r--src/qml/qml/qqmlmetatype.cpp21
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp414
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h12
-rw-r--r--src/qml/qml/qqmlopenmetaobject.cpp2
-rw-r--r--src/qml/qml/qqmlopenmetaobject_p.h4
-rw-r--r--src/qml/qml/qqmlproperty.cpp428
-rw-r--r--src/qml/qml/qqmlproperty_p.h44
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp750
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h639
-rw-r--r--src/qml/qml/qqmlpropertyindex_p.h (renamed from src/qml/qml/qqmlcompiler_p.h)128
-rw-r--r--src/qml/qml/qqmlpropertyvalueinterceptor_p.h4
-rw-r--r--src/qml/qml/qqmlproxymetaobject.cpp6
-rw-r--r--src/qml/qml/qqmlproxymetaobject_p.h4
-rw-r--r--src/qml/qml/qqmltypeloader.cpp646
-rw-r--r--src/qml/qml/qqmltypeloader_p.h116
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp2
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h2
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp9
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h8
-rw-r--r--src/qml/qml/qqmlvaluetypeproxybinding.cpp8
-rw-r--r--src/qml/qml/qqmlvaluetypeproxybinding_p.h8
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp39
-rw-r--r--src/qml/qml/qqmlvme.cpp1
-rw-r--r--src/qml/qml/qqmlvme_p.h4
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp68
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h17
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp63
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp76
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h3
-rw-r--r--src/qml/qml/v8/qv8engine.cpp3
78 files changed, 3154 insertions, 2637 deletions
diff --git a/src/qml/qml/ftw/ftw.pri b/src/qml/qml/ftw/ftw.pri
index addf1d9ff8..87d80d04bc 100644
--- a/src/qml/qml/ftw/ftw.pri
+++ b/src/qml/qml/ftw/ftw.pri
@@ -8,11 +8,11 @@ HEADERS += \
$$PWD/qqmlthread_p.h \
$$PWD/qfinitestack_p.h \
$$PWD/qrecursionwatcher_p.h \
- $$PWD/qdeletewatcher_p.h \
$$PWD/qrecyclepool_p.h \
$$PWD/qflagpointer_p.h \
$$PWD/qlazilyallocated_p.h \
$$PWD/qqmlnullablevalue_p.h \
+ $$PWD/qdeferredcleanup_p.h \
SOURCES += \
$$PWD/qintrusivelist.cpp \
@@ -21,4 +21,4 @@ SOURCES += \
# mirrors logic in $$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri
# clock_gettime() is implemented in librt on these systems
-contains(QT_CONFIG, clock-gettime):linux-*|hpux-*|solaris-*:LIBS_PRIVATE *= -lrt
+qtConfig(clock-gettime):linux-*|hpux-*|solaris-*:LIBS_PRIVATE *= -lrt
diff --git a/src/qml/qml/qqmlmemoryprofiler_p.h b/src/qml/qml/ftw/qdeferredcleanup_p.h
index 4b0ba823ba..6b59f04a77 100644
--- a/src/qml/qml/qqmlmemoryprofiler_p.h
+++ b/src/qml/qml/ftw/qdeferredcleanup_p.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QQMLMEMORYPROFILER_H
-#define QQMLMEMORYPROFILER_H
+#ifndef QDEFERREDCLEANUP_P_H
+#define QDEFERREDCLEANUP_P_H
//
// W A R N I N G
@@ -51,37 +51,24 @@
// We mean it.
//
-#include <private/qtqmlglobal_p.h>
+#include <QtCore/qglobal.h>
-QT_BEGIN_NAMESPACE
-
-class QUrl;
+#include <functional>
-class Q_QML_PRIVATE_EXPORT QQmlMemoryScope
-{
-public:
- explicit QQmlMemoryScope(const QUrl &url);
- explicit QQmlMemoryScope(const char *string);
- ~QQmlMemoryScope();
-
-private:
- bool pushed;
-};
+QT_BEGIN_NAMESPACE
-class Q_QML_PRIVATE_EXPORT QQmlMemoryProfiler
+struct QDeferredCleanup
{
-public:
- static void enable();
- static void disable();
- static bool isEnabled();
-
- static void clear();
- static void stats(int *allocCount, int *bytesAllocated);
- static void save(const char *filename);
+ std::function<void()> callback;
+ template <typename Callback>
+ QDeferredCleanup(Callback &&cb)
+ : callback(cb)
+ {}
+ ~QDeferredCleanup() { callback(); }
+ QDeferredCleanup(const QDeferredCleanup &) = delete;
+ QDeferredCleanup &operator=(const QDeferredCleanup &) = delete;
};
-#define QML_MEMORY_SCOPE_URL(url) QQmlMemoryScope _qml_memory_scope(url)
-#define QML_MEMORY_SCOPE_STRING(s) QQmlMemoryScope _qml_memory_scope(s)
-
QT_END_NAMESPACE
-#endif // QQMLMEMORYPROFILER_H
+
+#endif // QDEFERREDCLEANUP_P_H
diff --git a/src/qml/qml/ftw/qhashedstring.cpp b/src/qml/qml/ftw/qhashedstring.cpp
index 5c5d2a31ac..117670dbfc 100644
--- a/src/qml/qml/ftw/qhashedstring.cpp
+++ b/src/qml/qml/ftw/qhashedstring.cpp
@@ -39,30 +39,7 @@
#include "qhashedstring_p.h"
-inline quint32 stringHash(const QChar* data, int length)
-{
- return QV4::String::createHashValue(data, length, Q_NULLPTR);
-}
-inline quint32 stringHash(const char *data, int length)
-{
- return QV4::String::createHashValue(data, length, Q_NULLPTR);
-}
-
-void QHashedString::computeHash() const
-{
- m_hash = stringHash(constData(), length());
-}
-
-void QHashedStringRef::computeHash() const
-{
- m_hash = stringHash(m_data, m_length);
-}
-
-void QHashedCStringRef::computeHash() const
-{
- m_hash = stringHash(m_data, m_length);
-}
/*
A QHash has initially around pow(2, MinNumBits) buckets. For
diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h
index 6ff3e4a11b..9ee50ec931 100644
--- a/src/qml/qml/ftw/qhashedstring_p.h
+++ b/src/qml/qml/ftw/qhashedstring_p.h
@@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE
// #define QSTRINGHASH_LINK_DEBUG
class QHashedStringRef;
-class Q_AUTOTEST_EXPORT QHashedString : public QString
+class Q_QML_PRIVATE_EXPORT QHashedString : public QString
{
public:
inline QHashedString();
@@ -85,16 +85,20 @@ public:
static bool compare(const QChar *lhs, const QChar *rhs, int length);
static inline bool compare(const QChar *lhs, const char *rhs, int length);
static inline bool compare(const char *lhs, const char *rhs, int length);
+
+ static inline quint32 stringHash(const QChar* data, int length);
+ static inline quint32 stringHash(const char *data, int length);
+
private:
friend class QHashedStringRef;
friend class QStringHashNode;
- void computeHash() const;
+ inline void computeHash() const;
mutable quint32 m_hash;
};
class QHashedCStringRef;
-class Q_AUTOTEST_EXPORT QHashedStringRef
+class Q_QML_PRIVATE_EXPORT QHashedStringRef
{
public:
inline QHashedStringRef();
@@ -136,7 +140,7 @@ public:
private:
friend class QHashedString;
- void computeHash() const;
+ inline void computeHash() const;
const QChar *m_data;
int m_length;
@@ -163,7 +167,7 @@ public:
private:
friend class QHashedStringRef;
- void computeHash() const;
+ inline void computeHash() const;
const char *m_data;
int m_length;
@@ -1214,6 +1218,11 @@ bool QHashedStringRef::isLatin1() const
return true;
}
+void QHashedStringRef::computeHash() const
+{
+ m_hash = QHashedString::stringHash(m_data, m_length);
+}
+
bool QHashedStringRef::startsWithUpper() const
{
if (m_length < 1) return false;
@@ -1280,6 +1289,11 @@ void QHashedCStringRef::writeUtf16(quint16 *output) const
*output++ = *d++;
}
+void QHashedCStringRef::computeHash() const
+{
+ m_hash = QHashedString::stringHash(m_data, m_length);
+}
+
bool QHashedString::compare(const QChar *lhs, const char *rhs, int length)
{
Q_ASSERT(lhs && rhs);
@@ -1295,6 +1309,21 @@ bool QHashedString::compare(const char *lhs, const char *rhs, int length)
return 0 == ::memcmp(lhs, rhs, length);
}
+quint32 QHashedString::stringHash(const QChar *data, int length)
+{
+ return QV4::String::createHashValue(data, length, Q_NULLPTR);
+}
+
+quint32 QHashedString::stringHash(const char *data, int length)
+{
+ return QV4::String::createHashValue(data, length, Q_NULLPTR);
+}
+
+void QHashedString::computeHash() const
+{
+ m_hash = stringHash(constData(), length());
+}
+
QT_END_NAMESPACE
#endif // QHASHEDSTRING_P_H
diff --git a/src/qml/qml/ftw/qqmlthread.cpp b/src/qml/qml/ftw/qqmlthread.cpp
index 1523817c9e..ffa6e29290 100644
--- a/src/qml/qml/ftw/qqmlthread.cpp
+++ b/src/qml/qml/ftw/qqmlthread.cpp
@@ -55,7 +55,7 @@ public:
QQmlThreadPrivate(QQmlThread *);
QQmlThread *q;
- virtual void run();
+ void run() override;
inline void lock() { _mutex.lock(); }
inline void unlock() { _mutex.unlock(); }
@@ -81,12 +81,12 @@ public:
void threadEvent();
protected:
- virtual bool event(QEvent *);
+ bool event(QEvent *) override;
private:
struct MainObject : public QObject {
MainObject(QQmlThreadPrivate *p);
- virtual bool event(QEvent *e);
+ bool event(QEvent *e) override;
QQmlThreadPrivate *p;
};
MainObject m_mainObject;
diff --git a/src/qml/qml/ftw/qqmlthread_p.h b/src/qml/qml/ftw/qqmlthread_p.h
index 9f180b1f14..295235e255 100644
--- a/src/qml/qml/ftw/qqmlthread_p.h
+++ b/src/qml/qml/ftw/qqmlthread_p.h
@@ -142,7 +142,7 @@ void QQmlThread::callMethodInThread(void (O::*Member)())
struct I : public Message {
void (O::*Member)();
I(void (O::*Member)()) : Member(Member) {}
- virtual void call(QQmlThread *thread) {
+ void call(QQmlThread *thread) override {
O *me = static_cast<O *>(thread);
(me->*Member)();
}
@@ -157,7 +157,7 @@ void QQmlThread::callMethodInThread(void (O::*Member)(V), const T &arg)
void (O::*Member)(V);
T arg;
I(void (O::*Member)(V), const T &arg) : Member(Member), arg(arg) {}
- virtual void call(QQmlThread *thread) {
+ void call(QQmlThread *thread) override {
O *me = static_cast<O *>(thread);
(me->*Member)(arg);
}
@@ -173,7 +173,7 @@ void QQmlThread::callMethodInThread(void (O::*Member)(V, V2), const T &arg, cons
T arg;
T2 arg2;
I(void (O::*Member)(V, V2), const T &arg, const T2 &arg2) : Member(Member), arg(arg), arg2(arg2) {}
- virtual void call(QQmlThread *thread) {
+ void call(QQmlThread *thread) override {
O *me = static_cast<O *>(thread);
(me->*Member)(arg, arg2);
}
@@ -187,7 +187,7 @@ void QQmlThread::callMethodInMain(void (O::*Member)())
struct I : public Message {
void (O::*Member)();
I(void (O::*Member)()) : Member(Member) {}
- virtual void call(QQmlThread *thread) {
+ void call(QQmlThread *thread) override {
O *me = static_cast<O *>(thread);
(me->*Member)();
}
@@ -202,7 +202,7 @@ void QQmlThread::callMethodInMain(void (O::*Member)(V), const T &arg)
void (O::*Member)(V);
T arg;
I(void (O::*Member)(V), const T &arg) : Member(Member), arg(arg) {}
- virtual void call(QQmlThread *thread) {
+ void call(QQmlThread *thread) override {
O *me = static_cast<O *>(thread);
(me->*Member)(arg);
}
@@ -218,7 +218,7 @@ void QQmlThread::callMethodInMain(void (O::*Member)(V, V2), const T &arg, const
T arg;
T2 arg2;
I(void (O::*Member)(V, V2), const T &arg, const T2 &arg2) : Member(Member), arg(arg), arg2(arg2) {}
- virtual void call(QQmlThread *thread) {
+ void call(QQmlThread *thread) override {
O *me = static_cast<O *>(thread);
(me->*Member)(arg, arg2);
}
@@ -232,7 +232,7 @@ void QQmlThread::postMethodToThread(void (O::*Member)())
struct I : public Message {
void (O::*Member)();
I(void (O::*Member)()) : Member(Member) {}
- virtual void call(QQmlThread *thread) {
+ void call(QQmlThread *thread) override {
O *me = static_cast<O *>(thread);
(me->*Member)();
}
@@ -247,7 +247,7 @@ void QQmlThread::postMethodToThread(void (O::*Member)(V), const T &arg)
void (O::*Member)(V);
T arg;
I(void (O::*Member)(V), const T &arg) : Member(Member), arg(arg) {}
- virtual void call(QQmlThread *thread) {
+ void call(QQmlThread *thread) override {
O *me = static_cast<O *>(thread);
(me->*Member)(arg);
}
@@ -263,7 +263,7 @@ void QQmlThread::postMethodToThread(void (O::*Member)(V, V2), const T &arg, cons
T arg;
T2 arg2;
I(void (O::*Member)(V, V2), const T &arg, const T2 &arg2) : Member(Member), arg(arg), arg2(arg2) {}
- virtual void call(QQmlThread *thread) {
+ void call(QQmlThread *thread) override {
O *me = static_cast<O *>(thread);
(me->*Member)(arg, arg2);
}
@@ -277,7 +277,7 @@ void QQmlThread::postMethodToMain(void (O::*Member)())
struct I : public Message {
void (O::*Member)();
I(void (O::*Member)()) : Member(Member) {}
- virtual void call(QQmlThread *thread) {
+ void call(QQmlThread *thread) override {
O *me = static_cast<O *>(thread);
(me->*Member)();
}
@@ -292,7 +292,7 @@ void QQmlThread::postMethodToMain(void (O::*Member)(V), const T &arg)
void (O::*Member)(V);
T arg;
I(void (O::*Member)(V), const T &arg) : Member(Member), arg(arg) {}
- virtual void call(QQmlThread *thread) {
+ void call(QQmlThread *thread) override {
O *me = static_cast<O *>(thread);
(me->*Member)(arg);
}
@@ -308,7 +308,7 @@ void QQmlThread::postMethodToMain(void (O::*Member)(V, V2), const T &arg, const
T arg;
T2 arg2;
I(void (O::*Member)(V, V2), const T &arg, const T2 &arg2) : Member(Member), arg(arg), arg2(arg2) {}
- virtual void call(QQmlThread *thread) {
+ void call(QQmlThread *thread) override {
O *me = static_cast<O *>(thread);
(me->*Member)(arg, arg2);
}
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index 91d883c29f..8d8da3742d 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -12,7 +12,6 @@ SOURCES += \
$$PWD/qqmlpropertyvalueinterceptor.cpp \
$$PWD/qqmlproxymetaobject.cpp \
$$PWD/qqmlvme.cpp \
- $$PWD/qqmlcompileddata.cpp \
$$PWD/qqmlboundsignal.cpp \
$$PWD/qqmlmetatype.cpp \
$$PWD/qqmlstringconverters.cpp \
@@ -21,7 +20,6 @@ SOURCES += \
$$PWD/qqmlinfo.cpp \
$$PWD/qqmlerror.cpp \
$$PWD/qqmlvaluetype.cpp \
- $$PWD/qqmlaccessors.cpp \
$$PWD/qqmlxmlhttprequest.cpp \
$$PWD/qqmlcleanup.cpp \
$$PWD/qqmlpropertycache.cpp \
@@ -39,7 +37,6 @@ SOURCES += \
$$PWD/qqmlvaluetypeproxybinding.cpp \
$$PWD/qqmlglobal.cpp \
$$PWD/qqmlfile.cpp \
- $$PWD/qqmlmemoryprofiler.cpp \
$$PWD/qqmlplatform.cpp \
$$PWD/qqmlbinding.cpp \
$$PWD/qqmlabstracturlinterceptor.cpp \
@@ -51,7 +48,8 @@ SOURCES += \
$$PWD/qqmlfileselector.cpp \
$$PWD/qqmlobjectcreator.cpp \
$$PWD/qqmldirparser.cpp \
- $$PWD/qqmldelayedcallqueue.cpp
+ $$PWD/qqmldelayedcallqueue.cpp \
+ $$PWD/qqmlloggingcategory.cpp
HEADERS += \
$$PWD/qqmlglobal_p.h \
@@ -71,7 +69,6 @@ HEADERS += \
$$PWD/qqmlparserstatus.h \
$$PWD/qqmlproxymetaobject_p.h \
$$PWD/qqmlvme_p.h \
- $$PWD/qqmlcompiler_p.h \
$$PWD/qqmlengine_p.h \
$$PWD/qqmlexpression_p.h \
$$PWD/qqmlprivate.h \
@@ -89,10 +86,10 @@ HEADERS += \
$$PWD/qqmldata_p.h \
$$PWD/qqmlerror.h \
$$PWD/qqmlvaluetype_p.h \
- $$PWD/qqmlaccessors_p.h \
$$PWD/qqmlxmlhttprequest_p.h \
$$PWD/qqmlcleanup_p.h \
$$PWD/qqmlpropertycache_p.h \
+ $$PWD/qqmlpropertyindex_p.h \
$$PWD/qqmlnotifier_p.h \
$$PWD/qqmltypenotavailable_p.h \
$$PWD/qqmltypenamecache_p.h \
@@ -109,7 +106,6 @@ HEADERS += \
$$PWD/qqmlabstractbinding_p.h \
$$PWD/qqmlvaluetypeproxybinding_p.h \
$$PWD/qqmlfile.h \
- $$PWD/qqmlmemoryprofiler_p.h \
$$PWD/qqmlplatform_p.h \
$$PWD/qqmlbinding_p.h \
$$PWD/qqmlextensionplugin_p.h \
@@ -124,7 +120,8 @@ HEADERS += \
$$PWD/qqmlfileselector.h \
$$PWD/qqmlobjectcreator_p.h \
$$PWD/qqmldirparser_p.h \
- $$PWD/qqmldelayedcallqueue_p.h
+ $$PWD/qqmldelayedcallqueue_p.h \
+ $$PWD/qqmlloggingcategory_p.h
include(ftw/ftw.pri)
include(v8/v8.pri)
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index 8fb710ad9d..39764b8001 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -238,6 +238,9 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
}
+
+Q_QML_EXPORT int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject, const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason);
+
template<typename T>
int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
{
diff --git a/src/qml/qml/qqmlabstractbinding.cpp b/src/qml/qml/qqmlabstractbinding.cpp
index abaf95fa11..39d609454f 100644
--- a/src/qml/qml/qqmlabstractbinding.cpp
+++ b/src/qml/qml/qqmlabstractbinding.cpp
@@ -78,24 +78,26 @@ void QQmlAbstractBinding::addToObject()
QQmlData *data = QQmlData::get(obj, true);
- int coreIndex;
- if (QQmlPropertyData::decodeValueTypePropertyIndex(targetPropertyIndex(), &coreIndex) != -1) {
+ int coreIndex = targetPropertyIndex().coreIndex();
+ if (targetPropertyIndex().hasValueTypeIndex()) {
// Value type
// Find the value type proxy (if there is one)
QQmlValueTypeProxyBinding *proxy = 0;
if (data->hasBindingBit(coreIndex)) {
QQmlAbstractBinding *b = data->bindings;
- while (b && b->targetPropertyIndex() != coreIndex)
+ while (b && (b->targetPropertyIndex().coreIndex() != coreIndex ||
+ b->targetPropertyIndex().hasValueTypeIndex()))
b = b->nextBinding();
Q_ASSERT(b && b->isValueTypeProxy());
proxy = static_cast<QQmlValueTypeProxyBinding *>(b);
}
if (!proxy) {
- proxy = new QQmlValueTypeProxyBinding(obj, coreIndex);
+ proxy = new QQmlValueTypeProxyBinding(obj, QQmlPropertyIndex(coreIndex));
- Q_ASSERT(proxy->targetPropertyIndex() == coreIndex);
+ Q_ASSERT(proxy->targetPropertyIndex().coreIndex() == coreIndex);
+ Q_ASSERT(!proxy->targetPropertyIndex().hasValueTypeIndex());
Q_ASSERT(proxy->targetObject() == obj);
proxy->addToObject();
@@ -137,12 +139,13 @@ void QQmlAbstractBinding::removeFromObject()
next = nextBinding();
setNextBinding(0);
- int coreIndex;
- if (QQmlPropertyData::decodeValueTypePropertyIndex(targetPropertyIndex(), &coreIndex) != -1) {
+ int coreIndex = targetPropertyIndex().coreIndex();
+ if (targetPropertyIndex().hasValueTypeIndex()) {
// Find the value type binding
QQmlAbstractBinding *vtbinding = data->bindings;
- while (vtbinding->targetPropertyIndex() != coreIndex) {
+ while (vtbinding && (vtbinding->targetPropertyIndex().coreIndex() != coreIndex ||
+ vtbinding->targetPropertyIndex().hasValueTypeIndex())) {
vtbinding = vtbinding->nextBinding();
Q_ASSERT(vtbinding);
}
diff --git a/src/qml/qml/qqmlabstractbinding_p.h b/src/qml/qml/qqmlabstractbinding_p.h
index 45221a4bcd..bea2d253e4 100644
--- a/src/qml/qml/qqmlabstractbinding_p.h
+++ b/src/qml/qml/qqmlabstractbinding_p.h
@@ -76,13 +76,13 @@ public:
// Should return the encoded property index for the binding. Should return this value
// even if the binding is not enabled or added to an object.
// Encoding is: coreIndex | (valueTypeIndex << 16)
- int targetPropertyIndex() const { return m_targetIndex; }
+ QQmlPropertyIndex targetPropertyIndex() const { return m_targetIndex; }
// Should return the object for the binding. Should return this object even if the
// binding is not enabled or added to the object.
QObject *targetObject() const { return m_target.data(); }
- virtual void setEnabled(bool e, QQmlPropertyPrivate::WriteFlags f = QQmlPropertyPrivate::DontRemoveBinding) = 0;
+ virtual void setEnabled(bool e, QQmlPropertyData::WriteFlags f = QQmlPropertyData::DontRemoveBinding) = 0;
void addToObject();
void removeFromObject();
@@ -91,6 +91,8 @@ public:
inline QQmlAbstractBinding *nextBinding() const;
+ inline bool canUseAccessor() const
+ { return m_nextBinding.flag2(); }
struct RefCount {
RefCount() : refCount(0) {}
@@ -111,9 +113,16 @@ protected:
inline void setNextBinding(QQmlAbstractBinding *);
- int m_targetIndex;
+ QQmlPropertyIndex m_targetIndex;
+
+ // Pointer is the target object to which the binding binds
+ // flag1 is the updating flag
+ // flag2 is the enabled flag
QFlagPointer<QObject> m_target;
+
// Pointer to the next binding in the linked list of bindings.
+ // flag1 is used for addedToObject
+ // flag2 indicates if an accessor is can be used (i.e. there is no interceptor on the target)
QFlagPointer<QQmlAbstractBinding> m_nextBinding;
};
diff --git a/src/qml/qml/qqmlaccessors.cpp b/src/qml/qml/qqmlaccessors.cpp
deleted file mode 100644
index 7b0fafdc90..0000000000
--- a/src/qml/qml/qqmlaccessors.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlaccessors_p.h"
-
-#include "qqmldata_p.h"
-#include "qqmlnotifier_p.h"
-
-QT_BEGIN_NAMESPACE
-
-struct AccessorProperties {
- AccessorProperties();
-
- QReadWriteLock lock;
- QHash<const QMetaObject *, QQmlAccessorProperties::Properties> properties;
-};
-
-Q_GLOBAL_STATIC(AccessorProperties, accessorProperties)
-
-static void buildNameMask(QQmlAccessorProperties::Properties &properties)
-{
- quint32 mask = 0;
-
- for (int ii = 0; ii < properties.count; ++ii) {
- Q_ASSERT(strlen(properties.properties[ii].name) == properties.properties[ii].nameLength);
- Q_ASSERT(properties.properties[ii].nameLength > 0);
-
- mask |= (1 << qMin(31U, properties.properties[ii].nameLength - 1));
- }
-
- properties.nameMask = mask;
-}
-
-AccessorProperties::AccessorProperties()
-{
-}
-
-QQmlAccessorProperties::Properties::Properties(Property *properties, int count)
-: count(count), properties(properties)
-{
- buildNameMask(*this);
-}
-
-QQmlAccessorProperties::Properties
-QQmlAccessorProperties::properties(const QMetaObject *mo)
-{
- AccessorProperties *This = accessorProperties();
-
- QReadLocker lock(&This->lock);
- return This->properties.value(mo);
-}
-
-void QQmlAccessorProperties::registerProperties(const QMetaObject *mo, int count,
- Property *props)
-{
- Q_ASSERT(count > 0);
-
- Properties properties(props, count);
-
- AccessorProperties *This = accessorProperties();
-
- QWriteLocker lock(&This->lock);
-
- Q_ASSERT(!This->properties.contains(mo) || This->properties.value(mo) == properties);
-
- This->properties.insert(mo, properties);
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlaccessors_p.h b/src/qml/qml/qqmlaccessors_p.h
deleted file mode 100644
index 55562a5307..0000000000
--- a/src/qml/qml/qqmlaccessors_p.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLACCESSORS_P_H
-#define QQMLACCESSORS_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 <private/qtqmlglobal_p.h>
-#include <QtCore/qbytearray.h>
-#include <QtCore/qvector.h>
-#include <QtCore/qhash.h>
-#include <QtCore/QReadWriteLock>
-
-#if defined(Q_OS_QNX) || defined(Q_OS_LINUX)
-#include <stdint.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-class QObject;
-struct QMetaObject;
-class QQmlNotifier;
-
-// QML "accessor properties" allow V4 and V8 to bypass Qt's meta system to read and, more
-// importantly, subscribe to properties directly. Any property that is primarily read
-// from bindings is a candidate for inclusion as an accessor property.
-//
-// To define accessor properties, use the QML_DECLARE_PROPERTIES() and QML_DEFINE_PROPERTIES()
-// macros. The QML_DECLARE_PROPERTIES() macro is used to specify the properties, and the
-// QML_DEFINE_PROPERTIES() macro to register the properties with the
-// QQmlAccessorProperties singleton.
-//
-// A class with accessor properties must also add the Q_CLASSINFO("qt_HasQmlAccessors", "true")
-// tag to its declaration. This is essential for QML to maintain internal consistency,
-// and forgetting to do so will probably cause your application to qFatal() with a
-// helpful reminder of this requirement.
-//
-// It is important that QML_DEFINE_PROPERTIES() has been called before QML ever sees
-// the type with the accessor properties. As QML_DEFINE_PROPERTIES() is idempotent, it is
-// recommended to call it in the type's constructor as well as when the type is registered
-// as a QML element (if it ever is). QML_DEFINE_PROPERTIES() is a very cheap operation
-// if registration has already occurred.
-
-#define QML_DECLARE_PROPERTIES(type) \
- static volatile bool qqml_accessor_properties_isregistered_ ## type = false; \
- static QQmlAccessorProperties::Property qqml_accessor_properties_ ## type[] =
-
-#define QML_DEFINE_PROPERTIES(type) \
- do { \
- if (!qqml_accessor_properties_isregistered_ ## type) { \
- int count = sizeof(qqml_accessor_properties_ ## type) / \
- sizeof(QQmlAccessorProperties::Property); \
- QQmlAccessorProperties::registerProperties(&type::staticMetaObject, count, \
- qqml_accessor_properties_ ## type);\
- qqml_accessor_properties_isregistered_ ## type = true; \
- } \
- } while (false);
-
-#define QML_PRIVATE_ACCESSOR(clazz, cpptype, name, variable) \
- static void clazz ## _ ## name ## Read(QObject *o, void *rv) \
- { \
- clazz ## Private *d = clazz ## Private::get(static_cast<clazz *>(o)); \
- *static_cast<cpptype *>(rv) = d->variable; \
- }
-
-#define QML_PROPERTY_NAME(name) #name, sizeof #name - 1
-
-class QQmlAccessors
-{
-public:
- void (*read)(QObject *object, void *output);
- void (*notifier)(QObject *object, QQmlNotifier **notifier);
-};
-
-namespace QQmlAccessorProperties {
- struct Property {
- const char *name;
- unsigned int nameLength;
- qintptr data;
- QQmlAccessors *accessors;
- };
-
- struct Properties {
- inline Properties();
- Properties(Property *, int);
-
- bool operator==(const Properties &o) const {
- return count == o.count && properties == o.properties;
- }
-
- inline Property *property(const char *name);
-
- int count;
- Property *properties;
- quint32 nameMask;
- };
-
- Properties properties(const QMetaObject *);
- void Q_QML_PRIVATE_EXPORT registerProperties(const QMetaObject *, int, Property *);
-};
-
-QQmlAccessorProperties::Property *
-QQmlAccessorProperties::Properties::property(const char *name)
-{
- if (count == 0)
- return 0;
-
- const unsigned int length = (unsigned int)strlen(name);
-
- Q_ASSERT(length);
-
- if (nameMask & (1 << qMin(31U, length - 1))) {
-
- for (int ii = 0; ii < count; ++ii) {
- if (properties[ii].nameLength == length && 0 == qstrcmp(name, properties[ii].name))
- return &properties[ii];
- }
-
- }
-
- return 0;
-}
-
-QQmlAccessorProperties::Properties::Properties()
-: count(0), properties(0), nameMask(0)
-{
-}
-
-QT_END_NAMESPACE
-
-#endif // QQMLACCESSORS_P_H
diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp
index 8c342e0592..fef2da753b 100644
--- a/src/qml/qml/qqmlapplicationengine.cpp
+++ b/src/qml/qml/qqmlapplicationengine.cpp
@@ -69,6 +69,7 @@ void QQmlApplicationEnginePrivate::init()
q->connect(&statusMapper, SIGNAL(mapped(QObject*)),
q, SLOT(_q_finishLoad(QObject*)));
q->connect(q, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()));
+ q->connect(q, &QQmlApplicationEngine::exit, QCoreApplication::instance(), &QCoreApplication::exit);
#ifndef QT_NO_TRANSLATION
QTranslator* qtTranslator = new QTranslator;
if (qtTranslator->load(QLatin1String("qt_") + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
@@ -134,7 +135,7 @@ void QQmlApplicationEnginePrivate::_q_finishLoad(QObject *o)
break;
case QQmlComponent::Ready:
objects << c->create();
- q->objectCreated(objects.last(), c->url());
+ q->objectCreated(objects.constLast(), c->url());
break;
case QQmlComponent::Loading:
case QQmlComponent::Null:
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 1249e1b6c8..90698c3b24 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -42,7 +42,6 @@
#include "qqml.h"
#include "qqmlcontext.h"
#include "qqmlinfo.h"
-#include "qqmlcompiler_p.h"
#include "qqmldata_p.h"
#include <private/qqmlprofiler_p.h>
#include <private/qqmlexpression_p.h>
@@ -51,33 +50,36 @@
#include <private/qqmlbuiltinfunctions_p.h>
#include <private/qqmlvmemetaobject_p.h>
#include <private/qqmlvaluetypewrapper_p.h>
+#include <private/qv4qobjectwrapper_p.h>
+#include <private/qv4variantobject_p.h>
#include <QVariant>
#include <QtCore/qdebug.h>
QT_BEGIN_NAMESPACE
-QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContext *ctxt)
- : QQmlJavaScriptExpression(),
- QQmlAbstractBinding()
+QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QString &str, QObject *obj, QQmlContext *ctxt)
{
- setNotifyOnValueChanged(true);
- QQmlJavaScriptExpression::setContext(QQmlContextData::get(ctxt));
- setScopeObject(obj);
+ QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), property);
+ b->setNotifyOnValueChanged(true);
+ b->QQmlJavaScriptExpression::setContext(QQmlContextData::get(ctxt));
+ b->setScopeObject(obj);
- createQmlBinding(context(), obj, str, QString(), 0);
+ b->createQmlBinding(b->context(), obj, str, QString(), 0);
+
+ return b;
}
-QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlContext *ctxt)
- : QQmlJavaScriptExpression(),
- QQmlAbstractBinding()
+QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QQmlScriptString &script, QObject *obj, QQmlContext *ctxt)
{
+ QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), property);
+
if (ctxt && !ctxt->isValid())
- return;
+ return b;
const QQmlScriptStringPrivate *scriptPrivate = script.d.data();
if (!ctxt && (!scriptPrivate->context || !scriptPrivate->context->isValid()))
- return;
+ return b;
QString url;
QV4::Function *runtimeFunction = 0;
@@ -90,53 +92,61 @@ QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlConte
runtimeFunction = ctxtdata->typeCompilationUnit->runtimeFunctions.at(scriptPrivate->bindingId);
}
- setNotifyOnValueChanged(true);
- QQmlJavaScriptExpression::setContext(QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context));
- setScopeObject(obj ? obj : scriptPrivate->scope);
+ b->setNotifyOnValueChanged(true);
+ b->QQmlJavaScriptExpression::setContext(QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context));
+ b->setScopeObject(obj ? obj : scriptPrivate->scope);
- QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
+ QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(b->context()->engine)->v4engine();
if (runtimeFunction) {
- m_function.set(v4, QV4::FunctionObject::createQmlFunction(ctxtdata, scopeObject(), runtimeFunction));
+ b->m_function.set(v4, QV4::FunctionObject::createQmlFunction(ctxtdata, b->scopeObject(), runtimeFunction));
} else {
QString code = scriptPrivate->script;
- createQmlBinding(context(), scopeObject(), code, url, scriptPrivate->lineNumber);
+ b->createQmlBinding(b->context(), b->scopeObject(), code, url, scriptPrivate->lineNumber);
}
+
+ return b;
}
-QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContextData *ctxt)
- : QQmlJavaScriptExpression(),
- QQmlAbstractBinding()
+QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QString &str, QObject *obj, QQmlContextData *ctxt)
{
- setNotifyOnValueChanged(true);
- QQmlJavaScriptExpression::setContext(ctxt);
- setScopeObject(obj);
+ QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), property);
+
+ b->setNotifyOnValueChanged(true);
+ b->QQmlJavaScriptExpression::setContext(ctxt);
+ b->setScopeObject(obj);
- createQmlBinding(ctxt, obj, str, QString(), 0);
+ b->createQmlBinding(ctxt, obj, str, QString(), 0);
+
+ return b;
}
-QQmlBinding::QQmlBinding(const QString &str, QObject *obj,
- QQmlContextData *ctxt,
- const QString &url, quint16 lineNumber, quint16 columnNumber)
- : QQmlJavaScriptExpression(),
- QQmlAbstractBinding()
+QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QString &str, QObject *obj,
+ QQmlContextData *ctxt, const QString &url, quint16 lineNumber,
+ quint16 columnNumber)
{
+ QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), property);
+
Q_UNUSED(columnNumber);
- setNotifyOnValueChanged(true);
- QQmlJavaScriptExpression::setContext(ctxt);
- setScopeObject(obj);
+ b->setNotifyOnValueChanged(true);
+ b->QQmlJavaScriptExpression::setContext(ctxt);
+ b->setScopeObject(obj);
- createQmlBinding(ctxt, obj, str, url, lineNumber);
+ b->createQmlBinding(ctxt, obj, str, url, lineNumber);
+
+ return b;
}
-QQmlBinding::QQmlBinding(const QV4::Value &functionPtr, QObject *obj, QQmlContextData *ctxt)
- : QQmlJavaScriptExpression(),
- QQmlAbstractBinding()
+QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QV4::Value &functionPtr, QObject *obj, QQmlContextData *ctxt)
{
- setNotifyOnValueChanged(true);
- QQmlJavaScriptExpression::setContext(ctxt);
- setScopeObject(obj);
+ QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), property);
+
+ b->setNotifyOnValueChanged(true);
+ b->QQmlJavaScriptExpression::setContext(ctxt);
+ b->setScopeObject(obj);
- m_function.set(functionPtr.as<QV4::Object>()->engine(), functionPtr);
+ b->m_function.set(functionPtr.as<QV4::Object>()->engine(), functionPtr);
+
+ return b;
}
QQmlBinding::~QQmlBinding()
@@ -148,7 +158,7 @@ void QQmlBinding::setNotifyOnValueChanged(bool v)
QQmlJavaScriptExpression::setNotifyOnValueChanged(v);
}
-void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
+void QQmlBinding::update(QQmlPropertyData::WriteFlags flags)
{
if (!enabledFlag() || !context() || !context()->isValid())
return;
@@ -157,44 +167,75 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
if (QQmlData::wasDeleted(targetObject()))
return;
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
- QV4::Scope scope(ep->v4engine());
- QV4::ScopedFunctionObject f(scope, m_function.value());
- Q_ASSERT(f);
-
- if (updatingFlag()) {
- QQmlProperty p = QQmlPropertyPrivate::restore(targetObject(), getPropertyData(), 0);
+ // Check for a binding update loop
+ if (Q_UNLIKELY(updatingFlag())) {
+ QQmlPropertyData *d = nullptr;
+ QQmlPropertyData vtd;
+ getPropertyData(&d, &vtd);
+ Q_ASSERT(d);
+ QQmlProperty p = QQmlPropertyPrivate::restore(targetObject(), *d, &vtd, 0);
QQmlAbstractBinding::printBindingLoopError(p);
return;
}
-
- QQmlBindingProfiler prof(ep->profiler, this, f);
setUpdatingFlag(true);
- QQmlJavaScriptExpression::DeleteWatcher watcher(this);
+ DeleteWatcher watcher(this);
+
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
+ QV4::Scope scope(ep->v4engine());
+ QV4::ScopedFunctionObject f(scope, m_function.value());
+ Q_ASSERT(f);
- QQmlPropertyData pd = getPropertyData();
+ if (canUseAccessor())
+ flags.setFlag(QQmlPropertyData::BypassInterceptor);
- if (pd.propType == qMetaTypeId<QQmlBinding *>()) {
+ QQmlBindingProfiler prof(ep->profiler, this, f);
+ doUpdate(watcher, flags, scope, f);
- int idx = pd.coreIndex;
- Q_ASSERT(idx != -1);
+ if (!watcher.wasDeleted())
+ setUpdatingFlag(false);
+}
- QQmlBinding *t = this;
- int status = -1;
- void *a[] = { &t, 0, &status, &flags };
- QMetaObject::metacall(*m_target, QMetaObject::WriteProperty, idx, a);
+// QQmlBindingBinding is for target properties which are of type "binding" (instead of, say, int or
+// double). The reason for being is that GenericBinding::fastWrite needs a compile-time constant
+// expression for the switch for the compiler to generate the optimal code, but
+// qMetaTypeId<QQmlBinding *>() needs to be used for the ID. So QQmlBinding::newBinding uses that
+// to instantiate this class.
+class QQmlBindingBinding: public QQmlBinding
+{
+protected:
+ void doUpdate(const DeleteWatcher &,
+ QQmlPropertyData::WriteFlags flags, QV4::Scope &,
+ const QV4::ScopedFunctionObject &) Q_DECL_OVERRIDE Q_DECL_FINAL
+ {
+ Q_ASSERT(!m_targetIndex.hasValueTypeIndex());
+ QQmlPropertyData *pd = nullptr;
+ getPropertyData(&pd, nullptr);
+ QQmlBinding *thisPtr = this;
+ pd->writeProperty(*m_target, &thisPtr, flags);
+ }
+};
- } else {
+// For any target that's not a binding, we have a common doUpdate. However, depending on the type
+// of the target property, there is a specialized write method.
+class QQmlNonbindingBinding: public QQmlBinding
+{
+protected:
+ void doUpdate(const DeleteWatcher &watcher,
+ QQmlPropertyData::WriteFlags flags, QV4::Scope &scope,
+ const QV4::ScopedFunctionObject &f) Q_DECL_OVERRIDE Q_DECL_FINAL
+ {
+ auto ep = QQmlEnginePrivate::get(scope.engine);
ep->referenceScarceResources();
bool isUndefined = false;
- QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(&isUndefined));
+ QV4::ScopedCallData callData(scope);
+ QQmlJavaScriptExpression::evaluate(callData, &isUndefined, scope);
bool error = false;
if (!watcher.wasDeleted() && isAddedToObject() && !hasError())
- error = !write(pd, result, isUndefined, flags);
+ error = !write(scope.result, isUndefined, flags);
if (!watcher.wasDeleted()) {
@@ -211,66 +252,88 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
}
+ cancelPermanentGuards();
+
ep->dereferenceScarceResources();
}
- if (!watcher.wasDeleted())
- setUpdatingFlag(false);
-}
+ virtual bool write(const QV4::Value &result, bool isUndefined, QQmlPropertyData::WriteFlags flags) = 0;
+};
-// Returns true if successful, false if an error description was set on expression
-bool QQmlBinding::write(const QQmlPropertyData &core,
- const QV4::Value &result, bool isUndefined,
- QQmlPropertyPrivate::WriteFlags flags)
+template<int StaticPropType>
+class GenericBinding: public QQmlNonbindingBinding
{
- Q_ASSERT(m_target.data());
- Q_ASSERT(core.coreIndex != -1);
-
-#define QUICK_STORE(cpptype, conversion) \
- { \
- cpptype o = (conversion); \
- int status = -1; \
- void *argv[] = { &o, 0, &status, &flags }; \
- QMetaObject::metacall(m_target.data(), QMetaObject::WriteProperty, core.coreIndex, argv); \
- return true; \
- } \
-
-
- if (Q_LIKELY(!isUndefined && !core.isValueTypeVirtual())) {
- switch (core.propType) {
- case QMetaType::Int:
- if (result.isInteger())
- QUICK_STORE(int, result.integerValue())
- else if (result.isNumber())
- QUICK_STORE(int, result.doubleValue())
- break;
- case QMetaType::Double:
- if (result.isNumber())
- QUICK_STORE(double, result.asDouble())
- break;
- case QMetaType::Float:
- if (result.isNumber())
- QUICK_STORE(float, result.asDouble())
- break;
- case QMetaType::QString:
- if (result.isString())
- QUICK_STORE(QString, result.toQStringNoThrow())
- break;
- default:
- if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) {
- if (vtw->d()->valueType->typeId == core.propType) {
- return vtw->write(m_target.data(), core.coreIndex);
+protected:
+ // Returns true if successful, false if an error description was set on expression
+ Q_ALWAYS_INLINE bool write(const QV4::Value &result, bool isUndefined,
+ QQmlPropertyData::WriteFlags flags) Q_DECL_OVERRIDE Q_DECL_FINAL
+ {
+ Q_ASSERT(targetObject());
+
+ QQmlPropertyData *pd;
+ QQmlPropertyData vpd;
+ getPropertyData(&pd, &vpd);
+ Q_ASSERT(pd);
+
+ int propertyType = StaticPropType; // If the binding is specialized to a type, the if and switch below will be constant-folded.
+ if (propertyType == QMetaType::UnknownType)
+ propertyType = pd->propType();
+
+ if (Q_LIKELY(!isUndefined && !vpd.isValid())) {
+ switch (propertyType) {
+ case QMetaType::Bool:
+ if (result.isBoolean())
+ return doStore<bool>(result.booleanValue(), pd, flags);
+ else
+ return doStore<bool>(result.toBoolean(), pd, flags);
+ case QMetaType::Int:
+ if (result.isInteger())
+ return doStore<int>(result.integerValue(), pd, flags);
+ else if (result.isNumber())
+ return doStore<int>(result.doubleValue(), pd, flags);
+ break;
+ case QMetaType::Double:
+ if (result.isNumber())
+ return doStore<double>(result.asDouble(), pd, flags);
+ break;
+ case QMetaType::Float:
+ if (result.isNumber())
+ return doStore<float>(result.asDouble(), pd, flags);
+ break;
+ case QMetaType::QString:
+ if (result.isString())
+ return doStore<QString>(result.toQStringNoThrow(), pd, flags);
+ break;
+ default:
+ if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) {
+ if (vtw->d()->valueType->typeId == pd->propType()) {
+ return vtw->write(m_target.data(), pd->coreIndex());
+ }
}
+ break;
}
- break;
}
+
+ return slowWrite(*pd, vpd, result, isUndefined, flags);
+ }
+
+ template <typename T>
+ Q_ALWAYS_INLINE bool doStore(T value, const QQmlPropertyData *pd, QQmlPropertyData::WriteFlags flags) const
+ {
+ void *o = &value;
+ return pd->writeProperty(targetObject(), o, flags);
}
-#undef QUICK_STORE
+};
+Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core,
+ const QQmlPropertyData &valueTypeData,
+ const QV4::Value &result,
+ bool isUndefined, QQmlPropertyData::WriteFlags flags)
+{
QQmlEngine *engine = context()->engine;
QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(engine);
- int type = core.isValueTypeVirtual() ? core.valueTypePropType : core.propType;
+ int type = valueTypeData.isValid() ? valueTypeData.propType() : core.propType();
QQmlJavaScriptExpression::DeleteWatcher watcher(this);
@@ -282,7 +345,7 @@ bool QQmlBinding::write(const QQmlPropertyData &core,
value = QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QObject *> >());
} else if (result.isNull() && core.isQObject()) {
value = QVariant::fromValue((QObject *)0);
- } else if (core.propType == qMetaTypeId<QList<QUrl> >()) {
+ } else if (core.propType() == qMetaTypeId<QList<QUrl> >()) {
value = QQmlPropertyPrivate::resolvedUrlSequence(QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QUrl> >()), context());
} else if (!isVarProperty && type != qMetaTypeId<QJSValue>()) {
value = QV8Engine::getV4(v8engine)->toVariant(result, type);
@@ -301,28 +364,27 @@ bool QQmlBinding::write(const QQmlPropertyData &core,
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(m_target.data());
Q_ASSERT(vmemo);
- vmemo->setVMEProperty(core.coreIndex, result);
+ vmemo->setVMEProperty(core.coreIndex(), result);
} else if (isUndefined && core.isResettable()) {
void *args[] = { 0 };
- QMetaObject::metacall(m_target.data(), QMetaObject::ResetProperty, core.coreIndex, args);
+ QMetaObject::metacall(m_target.data(), QMetaObject::ResetProperty, core.coreIndex(), args);
} else if (isUndefined && type == qMetaTypeId<QVariant>()) {
- QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, QVariant(), context(), flags);
+ QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, valueTypeData, QVariant(), context(), flags);
} else if (type == qMetaTypeId<QJSValue>()) {
const QV4::FunctionObject *f = result.as<QV4::FunctionObject>();
if (f && f->isBinding()) {
delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
return false;
}
- QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, QVariant::fromValue(
+ QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, valueTypeData, QVariant::fromValue(
QJSValue(QV8Engine::getV4(v8engine), result.asReturnedValue())),
context(), flags);
} else if (isUndefined) {
- QString errorStr = QLatin1String("Unable to assign [undefined] to ");
- if (!QMetaType::typeName(type))
- errorStr += QLatin1String("[unknown property type]");
- else
- errorStr += QLatin1String(QMetaType::typeName(type));
- delayedError()->setErrorDescription(errorStr);
+ const QLatin1String typeName(QMetaType::typeName(type)
+ ? QMetaType::typeName(type)
+ : "[unknown property type]");
+ delayedError()->setErrorDescription(QLatin1String("Unable to assign [undefined] to ")
+ + typeName);
return false;
} else if (const QV4::FunctionObject *f = result.as<QV4::FunctionObject>()) {
if (f->isBinding())
@@ -330,7 +392,7 @@ bool QQmlBinding::write(const QQmlPropertyData &core,
else
delayedError()->setErrorDescription(QLatin1String("Unable to assign a function to a property of any type other than var."));
return false;
- } else if (!QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, value, context(), flags)) {
+ } else if (!QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, valueTypeData, value, context(), flags)) {
if (watcher.wasDeleted())
return true;
@@ -338,7 +400,8 @@ bool QQmlBinding::write(const QQmlPropertyData &core,
const char *valueType = 0;
const char *propertyType = 0;
- if (value.userType() == QMetaType::QObjectStar) {
+ const int userType = value.userType();
+ if (userType == QMetaType::QObjectStar) {
if (QObject *o = *(QObject *const *)value.constData()) {
valueType = o->metaObject()->className();
@@ -346,11 +409,11 @@ bool QQmlBinding::write(const QQmlPropertyData &core,
if (!propertyMetaObject.isNull())
propertyType = propertyMetaObject.className();
}
- } else if (value.userType() != QVariant::Invalid) {
- if (value.userType() == QMetaType::VoidStar)
+ } else if (userType != QVariant::Invalid) {
+ if (userType == QMetaType::Nullptr || userType == QMetaType::VoidStar)
valueType = "null";
else
- valueType = QMetaType::typeName(value.userType());
+ valueType = QMetaType::typeName(userType);
}
if (!valueType)
@@ -378,11 +441,12 @@ QVariant QQmlBinding::evaluate()
bool isUndefined = false;
QV4::Scope scope(ep->v4engine());
- QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(&isUndefined));
+ QV4::ScopedCallData callData(scope);
+ QQmlJavaScriptExpression::evaluate(callData, &isUndefined, scope);
ep->dereferenceScarceResources();
- return scope.engine->toVariant(result, qMetaTypeId<QList<QObject*> >());
+ return scope.engine->toVariant(scope.result, qMetaTypeId<QList<QObject*> >());
}
QString QQmlBinding::expressionIdentifier()
@@ -395,8 +459,7 @@ QString QQmlBinding::expressionIdentifier()
QString url = function->sourceFile();
quint16 lineNumber = function->compiledFunction->location.line;
quint16 columnNumber = function->compiledFunction->location.column;
-
- return url + QLatin1Char(':') + QString::number(lineNumber) + QLatin1Char(':') + QString::number(columnNumber);
+ return url + QString::asprintf(":%u:%u", uint(lineNumber), uint(columnNumber));
}
void QQmlBinding::expressionChanged()
@@ -409,11 +472,17 @@ void QQmlBinding::refresh()
update();
}
-void QQmlBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags)
+void QQmlBinding::setEnabled(bool e, QQmlPropertyData::WriteFlags flags)
{
setEnabledFlag(e);
setNotifyOnValueChanged(e);
+ m_nextBinding.setFlag2(); // Always use accessors, only not when:
+ if (auto interceptorMetaObject = QQmlInterceptorMetaObject::get(targetObject())) {
+ if (!m_targetIndex.isValid() || interceptorMetaObject->intercepts(m_targetIndex))
+ m_nextBinding.clearFlag2();
+ }
+
if (e)
update(flags);
}
@@ -427,29 +496,28 @@ QString QQmlBinding::expression() const
void QQmlBinding::setTarget(const QQmlProperty &prop)
{
- setTarget(prop.object(), QQmlPropertyPrivate::get(prop)->core);
+ auto pd = QQmlPropertyPrivate::get(prop);
+ setTarget(prop.object(), pd->core, &pd->valueTypeData);
}
-void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core)
+void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core, const QQmlPropertyData *valueType)
{
m_target = object;
if (!object) {
- m_targetIndex = -1;
+ m_targetIndex = QQmlPropertyIndex();
return;
}
- QQmlPropertyData pd = core;
-
- while (pd.isAlias()) {
- int coreIndex = pd.coreIndex;
- int valueTypeIndex = pd.getValueTypeCoreIndex();
+ int coreIndex = core.coreIndex();
+ int valueTypeIndex = valueType ? valueType->coreIndex() : -1;
+ for (bool isAlias = core.isAlias(); isAlias; ) {
QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
int aValueTypeIndex;
if (!vme->aliasTarget(coreIndex, &object, &coreIndex, &aValueTypeIndex)) {
m_target = 0;
- m_targetIndex = -1;
+ m_targetIndex = QQmlPropertyIndex();
return;
}
if (valueTypeIndex == -1)
@@ -458,25 +526,17 @@ void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core)
QQmlData *data = QQmlData::get(object, false);
if (!data || !data->propertyCache) {
m_target = 0;
- m_targetIndex = -1;
+ m_targetIndex = QQmlPropertyIndex();
return;
}
QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex);
Q_ASSERT(propertyData);
m_target = object;
- pd = *propertyData;
- if (valueTypeIndex != -1) {
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(pd.propType);
- Q_ASSERT(valueTypeMetaObject);
- QMetaProperty vtProp = valueTypeMetaObject->property(valueTypeIndex);
- pd.setFlags(pd.getFlags() | QQmlPropertyData::IsValueTypeVirtual);
- pd.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp);
- pd.valueTypePropType = vtProp.userType();
- pd.valueTypeCoreIndex = valueTypeIndex;
- }
+ isAlias = propertyData->isAlias();
+ coreIndex = propertyData->coreIndex();
}
- m_targetIndex = pd.encodedIndex();
+ m_targetIndex = QQmlPropertyIndex(coreIndex, valueTypeIndex);
QQmlData *data = QQmlData::get(*m_target, true);
if (!data->propertyCache) {
@@ -485,28 +545,110 @@ void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core)
}
}
-QQmlPropertyData QQmlBinding::getPropertyData() const
+void QQmlBinding::getPropertyData(QQmlPropertyData **propertyData, QQmlPropertyData *valueTypeData) const
{
- int coreIndex;
- int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(m_targetIndex, &coreIndex);
+ Q_ASSERT(propertyData);
QQmlData *data = QQmlData::get(*m_target, false);
Q_ASSERT(data && data->propertyCache);
- QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex);
- Q_ASSERT(propertyData);
+ *propertyData = data->propertyCache->property(m_targetIndex.coreIndex());
+ Q_ASSERT(*propertyData);
- QQmlPropertyData d = *propertyData;
- if (Q_UNLIKELY(valueTypeIndex != -1)) {
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d.propType);
+ if (Q_UNLIKELY(m_targetIndex.hasValueTypeIndex() && valueTypeData)) {
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType((*propertyData)->propType());
Q_ASSERT(valueTypeMetaObject);
- QMetaProperty vtProp = valueTypeMetaObject->property(valueTypeIndex);
- d.setFlags(d.getFlags() | QQmlPropertyData::IsValueTypeVirtual);
- d.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp);
- d.valueTypePropType = vtProp.userType();
- d.valueTypeCoreIndex = valueTypeIndex;
+ QMetaProperty vtProp = valueTypeMetaObject->property(m_targetIndex.valueTypeIndex());
+ valueTypeData->setFlags(QQmlPropertyData::flagsForProperty(vtProp));
+ valueTypeData->setPropType(vtProp.userType());
+ valueTypeData->setCoreIndex(m_targetIndex.valueTypeIndex());
+ }
+}
+
+class QObjectPointerBinding: public QQmlNonbindingBinding
+{
+ QQmlMetaObject targetMetaObject;
+
+public:
+ QObjectPointerBinding(QQmlEnginePrivate *engine, int propertyType)
+ : targetMetaObject(QQmlPropertyPrivate::rawMetaObjectForType(engine, propertyType))
+ {}
+
+protected:
+ Q_ALWAYS_INLINE bool write(const QV4::Value &result, bool isUndefined,
+ QQmlPropertyData::WriteFlags flags) Q_DECL_OVERRIDE Q_DECL_FINAL
+ {
+ QQmlPropertyData *pd;
+ QQmlPropertyData vtpd;
+ getPropertyData(&pd, &vtpd);
+ if (Q_UNLIKELY(isUndefined || vtpd.isValid()))
+ return slowWrite(*pd, vtpd, result, isUndefined, flags);
+
+ // Check if the result is a QObject:
+ QObject *resultObject = nullptr;
+ QQmlMetaObject resultMo;
+ if (result.isNull()) {
+ // Special case: we can always write a nullptr. Don't bother checking anything else.
+ return pd->writeProperty(targetObject(), &resultObject, flags);
+ } else if (auto wrapper = result.as<QV4::QObjectWrapper>()) {
+ resultObject = wrapper->object();
+ if (!resultObject)
+ return pd->writeProperty(targetObject(), &resultObject, flags);
+ if (QQmlData *ddata = QQmlData::get(resultObject, false))
+ resultMo = ddata->propertyCache;
+ if (resultMo.isNull()) {
+ resultMo = resultObject->metaObject();
+ }
+ } else if (auto variant = result.as<QV4::VariantObject>()) {
+ QVariant value = variant->d()->data;
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context());
+ resultMo = QQmlPropertyPrivate::rawMetaObjectForType(ep, value.userType());
+ if (resultMo.isNull())
+ return slowWrite(*pd, vtpd, result, isUndefined, flags);
+ resultObject = *static_cast<QObject *const *>(value.constData());
+ } else {
+ return slowWrite(*pd, vtpd, result, isUndefined, flags);
+ }
+
+ // Compare & set:
+ if (QQmlMetaObject::canConvert(resultMo, targetMetaObject)) {
+ return pd->writeProperty(targetObject(), &resultObject, flags);
+ } else if (!resultObject && QQmlMetaObject::canConvert(targetMetaObject, resultMo)) {
+ // In the case of a null QObject, we assign the null if there is
+ // any change that the null variant type could be up or down cast to
+ // the property type.
+ return pd->writeProperty(targetObject(), &resultObject, flags);
+ } else {
+ return slowWrite(*pd, vtpd, result, isUndefined, flags);
+ }
+ }
+};
+
+QQmlBinding *QQmlBinding::newBinding(QQmlEnginePrivate *engine, const QQmlPropertyData *property)
+{
+ if (property && property->isQObject())
+ return new QObjectPointerBinding(engine, property->propType());
+
+ const int type = (property && property->isFullyResolved()) ? property->propType() : QMetaType::UnknownType;
+
+ if (type == qMetaTypeId<QQmlBinding *>()) {
+ return new QQmlBindingBinding;
+ }
+
+ switch (type) {
+ case QMetaType::Bool:
+ return new GenericBinding<QMetaType::Bool>;
+ case QMetaType::Int:
+ return new GenericBinding<QMetaType::Int>;
+ case QMetaType::Double:
+ return new GenericBinding<QMetaType::Double>;
+ case QMetaType::Float:
+ return new GenericBinding<QMetaType::Float>;
+ case QMetaType::QString:
+ return new GenericBinding<QMetaType::QString>;
+ default:
+ return new GenericBinding<QMetaType::UnknownType>;
}
- return d;
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index 45c360f07e..6d42a8ea8a 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -72,24 +72,24 @@ class Q_QML_PRIVATE_EXPORT QQmlBinding : public QQmlJavaScriptExpression,
{
friend class QQmlAbstractBinding;
public:
- QQmlBinding(const QString &, QObject *, QQmlContext *);
- QQmlBinding(const QQmlScriptString &, QObject *, QQmlContext *);
- QQmlBinding(const QString &, QObject *, QQmlContextData *);
- QQmlBinding(const QString &, QObject *, QQmlContextData *,
- const QString &url, quint16 lineNumber, quint16 columnNumber);
- QQmlBinding(const QV4::Value &, QObject *, QQmlContextData *);
+ static QQmlBinding *create(const QQmlPropertyData *, const QString &, QObject *, QQmlContext *);
+ static QQmlBinding *create(const QQmlPropertyData *, const QQmlScriptString &, QObject *, QQmlContext *);
+ static QQmlBinding *create(const QQmlPropertyData *, const QString &, QObject *, QQmlContextData *);
+ static QQmlBinding *create(const QQmlPropertyData *, const QString &, QObject *, QQmlContextData *,
+ const QString &url, quint16 lineNumber, quint16 columnNumber);
+ static QQmlBinding *create(const QQmlPropertyData *, const QV4::Value &, QObject *, QQmlContextData *);
~QQmlBinding();
void setTarget(const QQmlProperty &);
- void setTarget(QObject *, const QQmlPropertyData &);
+ void setTarget(QObject *, const QQmlPropertyData &, const QQmlPropertyData *valueType);
void setNotifyOnValueChanged(bool);
void refresh() Q_DECL_OVERRIDE;
- void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding) Q_DECL_OVERRIDE;
+ void setEnabled(bool, QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding) Q_DECL_OVERRIDE;
QString expression() const Q_DECL_OVERRIDE;
- void update(QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding);
+ void update(QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding);
typedef int Identifier;
enum {
@@ -101,17 +101,24 @@ public:
QString expressionIdentifier() Q_DECL_OVERRIDE;
void expressionChanged() Q_DECL_OVERRIDE;
+protected:
+ virtual void doUpdate(const DeleteWatcher &watcher,
+ QQmlPropertyData::WriteFlags flags, QV4::Scope &scope,
+ const QV4::ScopedFunctionObject &f) = 0;
+
+ void getPropertyData(QQmlPropertyData **propertyData, QQmlPropertyData *valueTypeData) const;
+ int getPropertyType() const;
+
+ bool slowWrite(const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData,
+ const QV4::Value &result, bool isUndefined, QQmlPropertyData::WriteFlags flags);
+
private:
inline bool updatingFlag() const;
inline void setUpdatingFlag(bool);
inline bool enabledFlag() const;
inline void setEnabledFlag(bool);
- QQmlPropertyData getPropertyData() const;
-
- bool write(const QQmlPropertyData &core,
- const QV4::Value &result, bool isUndefined,
- QQmlPropertyPrivate::WriteFlags flags);
+ static QQmlBinding *newBinding(QQmlEnginePrivate *engine, const QQmlPropertyData *property);
};
bool QQmlBinding::updatingFlag() const
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index f423a7d452..4e63790290 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -51,9 +51,9 @@
#include <private/qqmlprofiler_p.h>
#include <private/qqmldebugconnector_p.h>
#include <private/qqmldebugserviceinterfaces_p.h>
-#include <private/qqmlcompiler_p.h>
#include "qqmlinfo.h"
+#include <private/qjsvalue_p.h>
#include <private/qv4value_p.h>
#include <private/qv4qobjectwrapper_p.h>
@@ -80,8 +80,8 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
// Add some leading whitespace to account for the binding's column offset.
// It's 2 off because a, we start counting at 1 and b, the '(' below is not counted.
- function.fill(QChar(QChar::Space), qMax(column, (quint16)2) - 2);
- function += QStringLiteral("(function ") + handlerName + QLatin1Char('(');
+ function += QString(qMax(column, (quint16)2) - 2, QChar(QChar::Space))
+ + QLatin1String("(function ") + handlerName + QLatin1Char('(');
if (parameterString.isEmpty()) {
QString error;
@@ -97,7 +97,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
} else
function += parameterString;
- function += QStringLiteral(") { ") + expression + QStringLiteral(" })");
+ function += QLatin1String(") { ") + expression + QLatin1String(" })");
m_function.set(v4, evalFunction(context(), scopeObject(), function, fileName, line));
if (m_function.isNullOrUndefined())
@@ -206,10 +206,10 @@ void QQmlBoundSignalExpression::evaluate(void **a)
ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
- QVarLengthArray<int, 9> dummy;
+ QQmlMetaObject::ArgTypeStorage storage;
//TODO: lookup via signal index rather than method index as an optimization
int methodIndex = QMetaObjectPrivate::signal(m_target->metaObject(), m_index).methodIndex();
- int *argsTypes = QQmlMetaObject(m_target).methodParameterTypes(methodIndex, dummy, 0);
+ int *argsTypes = QQmlMetaObject(m_target).methodParameterTypes(methodIndex, &storage, 0);
int argCount = argsTypes ? *argsTypes : 0;
QV4::ScopedCallData callData(scope, argCount);
@@ -218,7 +218,9 @@ void QQmlBoundSignalExpression::evaluate(void **a)
//### ideally we would use metaTypeToJS, however it currently gives different results
// for several cases (such as QVariant type and QObject-derived types)
//args[ii] = engine->metaTypeToJS(type, a[ii + 1]);
- if (type == QMetaType::QVariant) {
+ if (type == qMetaTypeId<QJSValue>()) {
+ callData->args[ii] = *QJSValuePrivate::getValue(reinterpret_cast<QJSValue *>(a[ii + 1]));
+ } else if (type == QMetaType::QVariant) {
callData->args[ii] = scope.engine->fromVariant(*((QVariant *)a[ii + 1]));
} else if (type == QMetaType::Int) {
//### optimization. Can go away if we switch to metaTypeToJS, or be expanded otherwise
@@ -235,7 +237,7 @@ void QQmlBoundSignalExpression::evaluate(void **a)
}
}
- QQmlJavaScriptExpression::evaluate(callData, 0);
+ QQmlJavaScriptExpression::evaluate(callData, 0, scope);
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
}
@@ -257,7 +259,7 @@ void QQmlBoundSignalExpression::evaluate(const QList<QVariant> &args)
callData->args[ii] = scope.engine->fromVariant(args[ii]);
}
- QQmlJavaScriptExpression::evaluate(callData, 0);
+ QQmlJavaScriptExpression::evaluate(callData, 0, scope);
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
}
diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h
index 10c59b07c1..e940ca7401 100644
--- a/src/qml/qml/qqmlboundsignal_p.h
+++ b/src/qml/qml/qqmlboundsignal_p.h
@@ -79,8 +79,8 @@ public:
QQmlContextData *ctxt, QObject *scope, QV4::Function *runtimeFunction);
// inherited from QQmlJavaScriptExpression.
- virtual QString expressionIdentifier();
- virtual void expressionChanged();
+ QString expressionIdentifier() override;
+ void expressionChanged() override;
// evaluation of a bound signal expression doesn't return any value
void evaluate(void **a);
diff --git a/src/qml/qml/qqmlcompileddata.cpp b/src/qml/qml/qqmlcompileddata.cpp
deleted file mode 100644
index b25792054c..0000000000
--- a/src/qml/qml/qqmlcompileddata.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlcompiler_p.h"
-#include "qqmlengine.h"
-#include "qqmlcomponent.h"
-#include "qqmlcomponent_p.h"
-#include "qqmlcontext.h"
-#include "qqmlcontext_p.h"
-#include "qqmlpropertymap.h"
-#ifdef QML_THREADED_VME_INTERPRETER
-#include "qqmlvme_p.h"
-#endif
-
-#include <QtCore/qdebug.h>
-
-#include <private/qobject_p.h>
-
-QT_BEGIN_NAMESPACE
-
-QQmlCompiledData::QQmlCompiledData(QQmlEngine *engine)
-: engine(engine), metaTypeId(-1), listMetaTypeId(-1), isRegisteredWithEngine(false)
-{
- Q_ASSERT(engine);
-}
-
-void QQmlCompiledData::destroy()
-{
- if (engine && hasEngine())
- QQmlEnginePrivate::deleteInEngineThread(engine, this);
- else
- delete this;
-}
-
-QQmlCompiledData::~QQmlCompiledData()
-{
- if (isRegisteredWithEngine)
- QQmlEnginePrivate::get(engine)->unregisterInternalCompositeType(this);
-
- clear();
-
- for (QHash<int, TypeReference*>::Iterator resolvedType = resolvedTypes.begin(), end = resolvedTypes.end();
- resolvedType != end; ++resolvedType) {
- if ((*resolvedType)->component)
- (*resolvedType)->component->release();
- if ((*resolvedType)->typePropertyCache)
- (*resolvedType)->typePropertyCache->release();
- }
- qDeleteAll(resolvedTypes);
- resolvedTypes.clear();
-}
-
-void QQmlCompiledData::clear()
-{
-}
-
-/*!
-Returns the property cache, if one alread exists. The cache is not referenced.
-*/
-QQmlPropertyCache *QQmlCompiledData::TypeReference::propertyCache() const
-{
- if (type)
- return typePropertyCache;
- else
- return component->compilationUnit->rootPropertyCache();
-}
-
-/*!
-Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
-*/
-QQmlPropertyCache *QQmlCompiledData::TypeReference::createPropertyCache(QQmlEngine *engine)
-{
- if (typePropertyCache) {
- return typePropertyCache;
- } else if (type) {
- typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type->metaObject());
- typePropertyCache->addref();
- return typePropertyCache;
- } else {
- return component->compilationUnit->rootPropertyCache();
- }
-}
-
-template <typename T>
-bool qtTypeInherits(const QMetaObject *mo) {
- while (mo) {
- if (mo == &T::staticMetaObject)
- return true;
- mo = mo->superClass();
- }
- return false;
-}
-
-void QQmlCompiledData::TypeReference::doDynamicTypeCheck()
-{
- const QMetaObject *mo = 0;
- if (typePropertyCache)
- mo = typePropertyCache->firstCppMetaObject();
- else if (type)
- mo = type->metaObject();
- else if (component)
- mo = component->compilationUnit->rootPropertyCache()->firstCppMetaObject();
- isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
-}
-
-void QQmlCompiledData::initialize(QQmlEngine *engine)
-{
- Q_ASSERT(!hasEngine());
- QQmlCleanup::addToEngine(engine);
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
- if (compilationUnit && !compilationUnit->engine)
- compilationUnit->linkToEngine(v4);
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index eb4f590222..b78028dcf9 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -41,7 +41,6 @@
#include "qqmlcomponent_p.h"
#include "qqmlcomponentattached_p.h"
-#include "qqmlcompiler_p.h"
#include "qqmlcontext_p.h"
#include "qqmlengine_p.h"
#include "qqmlvme_p.h"
@@ -62,6 +61,7 @@
#include <private/qv4objectiterator_p.h>
#include <private/qv4qobjectwrapper_p.h>
+#include <QDir>
#include <QStack>
#include <QStringList>
#include <QThreadStorage>
@@ -335,14 +335,11 @@ void QQmlComponentPrivate::typeDataProgress(QQmlTypeData *, qreal p)
void QQmlComponentPrivate::fromTypeData(QQmlTypeData *data)
{
url = data->finalUrl();
- QQmlCompiledData *c = data->compiledData();
+ compilationUnit = data->compilationUnit();
- if (!c) {
+ if (!compilationUnit) {
Q_ASSERT(data->isError());
state.errors = data->errors();
- } else {
- cc = c;
- cc->addref();
}
data->release();
@@ -356,10 +353,7 @@ void QQmlComponentPrivate::clear()
typeData = 0;
}
- if (cc) {
- cc->release();
- cc = 0;
- }
+ compilationUnit = nullptr;
}
/*!
@@ -382,7 +376,7 @@ QQmlComponent::~QQmlComponent()
if (isError()) {
qWarning() << "This may have been caused by one of the following errors:";
- foreach (const QQmlError &error, d->state.errors)
+ for (const QQmlError &error : qAsConst(d->state.errors))
qWarning().nospace().noquote() << QLatin1String(" ") << error;
}
@@ -393,8 +387,6 @@ QQmlComponent::~QQmlComponent()
d->typeData->unregisterCallback(d);
d->typeData->release();
}
- if (d->cc)
- d->cc->release();
}
/*!
@@ -422,7 +414,7 @@ QQmlComponent::Status QQmlComponent::status() const
return Loading;
else if (!d->state.errors.isEmpty())
return Error;
- else if (d->engine && d->cc)
+ else if (d->engine && d->compilationUnit)
return Ready;
else
return Null;
@@ -558,20 +550,20 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, const QString &fileName,
: QQmlComponent(engine, parent)
{
Q_D(QQmlComponent);
- d->loadUrl(d->engine->baseUrl().resolved(QUrl::fromLocalFile(fileName)), mode);
+ const QUrl url = QDir::isAbsolutePath(fileName) ? QUrl::fromLocalFile(fileName) : d->engine->baseUrl().resolved(QUrl(fileName));
+ d->loadUrl(url, mode);
}
/*!
\internal
*/
-QQmlComponent::QQmlComponent(QQmlEngine *engine, QQmlCompiledData *cc, int start, QObject *parent)
+QQmlComponent::QQmlComponent(QQmlEngine *engine, QV4::CompiledData::CompilationUnit *compilationUnit, int start, QObject *parent)
: QQmlComponent(engine, parent)
{
Q_D(QQmlComponent);
- d->cc = cc;
- cc->addref();
+ d->compilationUnit = compilationUnit;
d->start = start;
- d->url = cc->compilationUnit->url();
+ d->url = compilationUnit->url();
d->progress = 1.0;
}
@@ -717,7 +709,7 @@ QString QQmlComponent::errorString() const
QString ret;
if(!isError())
return ret;
- foreach(const QQmlError &e, d->state.errors) {
+ for (const QQmlError &e : d->state.errors) {
ret += e.url().toString() + QLatin1Char(':') +
QString::number(e.line()) + QLatin1Char(' ') +
e.description() + QLatin1Char('\n');
@@ -864,7 +856,7 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
enginePriv->referenceScarceResources();
QObject *rv = 0;
- state.creator.reset(new QQmlObjectCreator(context, cc, creationContext));
+ state.creator.reset(new QQmlObjectCreator(context, compilationUnit, creationContext));
rv = state.creator->create(start);
if (!rv)
state.errors = state.creator->errors;
@@ -884,11 +876,13 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
depthIncreased = false;
}
- QQmlEngineDebugService *service = QQmlDebugConnector::service<QQmlEngineDebugService>();
- if (service && rv) {
- if (!context->isInternal)
- context->asQQmlContextPrivate()->instances.append(rv);
- service->objectCreated(engine, rv);
+ if (rv) {
+ if (QQmlEngineDebugService *service =
+ QQmlDebugConnector::service<QQmlEngineDebugService>()) {
+ if (!context->isInternal)
+ context->asQQmlContextPrivate()->instances.append(rv);
+ service->objectCreated(engine, rv);
+ }
}
return rv;
@@ -905,7 +899,7 @@ void QQmlComponentPrivate::beginDeferred(QQmlEnginePrivate *enginePriv,
Q_ASSERT(ddata->deferredData);
QQmlData::DeferredData *deferredData = ddata->deferredData;
QQmlContextData *creationContext = 0;
- state->creator.reset(new QQmlObjectCreator(deferredData->context->parent, deferredData->compiledData, creationContext));
+ state->creator.reset(new QQmlObjectCreator(deferredData->context->parent, deferredData->compilationUnit, creationContext));
if (!state->creator->populateDeferredProperties(object))
state->errors << state->creator->errors;
}
@@ -1049,9 +1043,9 @@ void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context,
QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(d->engine);
- p->compiledData = d->cc;
- p->compiledData->addref();
- p->creator.reset(new QQmlObjectCreator(contextData, d->cc, d->creationContext, p.data()));
+ p->compilationUnit = d->compilationUnit;
+ p->enginePriv = enginePriv;
+ p->creator.reset(new QQmlObjectCreator(contextData, d->compilationUnit, d->creationContext, p.data()));
p->subComponentToCreate = d->start;
enginePriv->incubate(incubator, forContextData);
@@ -1065,8 +1059,9 @@ namespace Heap {
struct QmlIncubatorObject : Object {
QmlIncubatorObject(QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous);
+ ~QmlIncubatorObject() { parent.destroy(); }
QScopedPointer<QQmlComponentIncubator> incubator;
- QPointer<QObject> parent;
+ QQmlQPointer<QObject> parent;
QV4::Value valuemap;
QV4::Value statusChanged;
Pointer<Heap::QmlContext> qmlContext;
@@ -1103,13 +1098,13 @@ public:
, incubatorObject(inc)
{}
- virtual void statusChanged(Status s) {
+ void statusChanged(Status s) override {
QV4::Scope scope(incubatorObject->internalClass->engine);
QV4::Scoped<QV4::QmlIncubatorObject> i(scope, incubatorObject);
i->statusChanged(s);
}
- virtual void setInitialState(QObject *o) {
+ void setInitialState(QObject *o) override {
QV4::Scope scope(incubatorObject->internalClass->engine);
QV4::Scoped<QV4::QmlIncubatorObject> i(scope, incubatorObject);
i->setInitialState(o);
@@ -1143,7 +1138,7 @@ static void QQmlComponent_setQmlParent(QObject *me, QObject *parent)
}
/*!
- \qmlmethod object Component::createObject(Item parent, object properties)
+ \qmlmethod object Component::createObject(QtObject parent, object properties)
Creates and returns an object instance of this component that will have
the given \a parent and \a properties. The \a properties argument is optional.
@@ -1184,7 +1179,7 @@ static void QQmlComponent_setQmlParent(QObject *me, QObject *parent)
*/
-static void setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v)
+void QQmlComponentPrivate::setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v)
{
QV4::Scope scope(engine);
QV4::ScopedObject object(scope);
@@ -1273,7 +1268,7 @@ void QQmlComponent::createObject(QQmlV4Function *args)
if (!valuemap->isUndefined()) {
QV4::Scoped<QV4::QmlContext> qmlContext(scope, v4->qmlContext());
- setInitialProperties(v4, qmlContext, object, valuemap);
+ QQmlComponentPrivate::setInitialProperties(v4, qmlContext, object, valuemap);
}
d->completeCreate();
@@ -1492,8 +1487,9 @@ QQmlComponentExtension::~QQmlComponentExtension()
QV4::Heap::QmlIncubatorObject::QmlIncubatorObject(QQmlIncubator::IncubationMode m)
: valuemap(QV4::Primitive::undefinedValue())
, statusChanged(QV4::Primitive::undefinedValue())
- , qmlContext(0)
{
+ parent.init();
+ qmlContext = nullptr;
incubator.reset(new QQmlComponentIncubator(this, m));
}
@@ -1506,7 +1502,7 @@ void QV4::QmlIncubatorObject::setInitialState(QObject *o)
QV4::Scope scope(v4);
QV4::ScopedObject obj(scope, QV4::QObjectWrapper::wrap(v4, o));
QV4::Scoped<QV4::QmlContext> qmlCtxt(scope, d()->qmlContext);
- setInitialProperties(v4, qmlCtxt, obj, d()->valuemap);
+ QQmlComponentPrivate::setInitialProperties(v4, qmlCtxt, obj, d()->valuemap);
}
}
@@ -1537,7 +1533,7 @@ void QV4::QmlIncubatorObject::statusChanged(QQmlIncubator::Status s)
QV4::ScopedCallData callData(scope, 1);
callData->thisObject = this;
callData->args[0] = QV4::Primitive::fromUInt32(s);
- f->call(callData);
+ f->call(scope, callData);
if (scope.hasException()) {
QQmlError error = scope.engine->catchExceptionAsQmlError();
QQmlEnginePrivate::warning(QQmlEnginePrivate::get(scope.engine->qmlEngine()), error);
diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h
index aefbf20aff..ca60f01eb5 100644
--- a/src/qml/qml/qqmlcomponent.h
+++ b/src/qml/qml/qqmlcomponent.h
@@ -55,10 +55,15 @@ class QQmlEngine;
class QQmlComponent;
class QQmlIncubator;
class QQmlV4Function;
-class QQmlCompiledData;
class QQmlComponentPrivate;
class QQmlComponentAttached;
+namespace QV4 {
+namespace CompiledData {
+struct CompilationUnit;
+}
+}
+
class Q_QML_EXPORT QQmlComponent : public QObject
{
Q_OBJECT
@@ -122,7 +127,7 @@ protected:
Q_INVOKABLE void incubateObject(QQmlV4Function *);
private:
- QQmlComponent(QQmlEngine *, QQmlCompiledData *, int, QObject *parent);
+ QQmlComponent(QQmlEngine *, QV4::CompiledData::CompilationUnit *compilationUnit, int, QObject *parent);
Q_DISABLE_COPY(QQmlComponent)
friend class QQmlTypeData;
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index 039b267433..d01a987acc 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -71,7 +71,6 @@ QT_BEGIN_NAMESPACE
class QQmlComponent;
class QQmlEngine;
-class QQmlCompiledData;
class QQmlComponentAttached;
class Q_QML_PRIVATE_EXPORT QQmlComponentPrivate : public QObjectPrivate, public QQmlTypeData::TypeDataCallback
@@ -80,17 +79,18 @@ class Q_QML_PRIVATE_EXPORT QQmlComponentPrivate : public QObjectPrivate, public
public:
QQmlComponentPrivate()
- : typeData(0), progress(0.), start(-1), cc(0), engine(0), creationContext(0), depthIncreased(false) {}
+ : typeData(0), progress(0.), start(-1), engine(0), creationContext(0), depthIncreased(false) {}
void loadUrl(const QUrl &newUrl, QQmlComponent::CompilationMode mode = QQmlComponent::PreferSynchronous);
QObject *beginCreate(QQmlContextData *);
void completeCreate();
void initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate);
+ static void setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v);
QQmlTypeData *typeData;
- virtual void typeDataReady(QQmlTypeData *);
- virtual void typeDataProgress(QQmlTypeData *, qreal);
+ void typeDataReady(QQmlTypeData *) override;
+ void typeDataProgress(QQmlTypeData *, qreal) override;
void fromTypeData(QQmlTypeData *data);
@@ -98,7 +98,7 @@ public:
qreal progress;
int start;
- QQmlCompiledData *cc;
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
struct ConstructionState {
ConstructionState()
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index b3081ddbe6..018841b9b1 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -383,7 +383,7 @@ QVariant QQmlContext::contextProperty(const QString &name) const
QQmlPropertyData *property =
QQmlPropertyCache::property(data->engine, obj, name, data, local);
- if (property) value = obj->metaObject()->property(property->coreIndex).read(obj);
+ if (property) value = obj->metaObject()->property(property->coreIndex()).read(obj);
}
if (!value.isValid() && parentContext())
value = parentContext()->contextProperty(name);
@@ -524,7 +524,7 @@ QQmlContextData::QQmlContextData(QQmlContext *ctxt)
: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false),
isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false),
publicContext(ctxt), activeVMEData(0), componentObjectIndex(-1),
- contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
+ contextObject(0), childContexts(0), nextChild(0), prevChild(0),
expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
componentAttached(0)
{
@@ -628,9 +628,6 @@ void QQmlContextData::destroy()
}
contextGuards = 0;
- if (imports)
- imports->release();
-
delete [] idValues;
if (isInternal)
diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h
index 05ce39401e..62cd3d4877 100644
--- a/src/qml/qml/qqmlcontext_p.h
+++ b/src/qml/qml/qqmlcontext_p.h
@@ -174,7 +174,7 @@ public:
QString urlString() const;
// List of imports that apply to this context
- QQmlTypeNameCache *imports;
+ QQmlRefPointer<QQmlTypeNameCache> imports;
// My children
QQmlContextData *childContexts;
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index 2d0ebad764..13d708bc17 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -66,14 +66,15 @@ Heap::QmlContextWrapper::QmlContextWrapper(QQmlContextData *context, QObject *sc
, ownsContext(ownsContext)
, isNullWrapper(false)
, context(context)
- , scopeObject(scopeObject)
{
+ this->scopeObject.init(scopeObject);
}
Heap::QmlContextWrapper::~QmlContextWrapper()
{
if (context && ownsContext)
context->destroy();
+ scopeObject.destroy();
}
ReturnedValue QmlContextWrapper::qmlScope(ExecutionEngine *v4, QQmlContextData *ctxt, QObject *scope)
diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h
index ca7fcf1d75..2b8c16f274 100644
--- a/src/qml/qml/qqmlcontextwrapper_p.h
+++ b/src/qml/qml/qqmlcontextwrapper_p.h
@@ -71,7 +71,7 @@ struct QmlContextWrapper : Object {
bool isNullWrapper;
QQmlGuardedContextData context;
- QPointer<QObject> scopeObject;
+ QQmlQPointer<QObject> scopeObject;
};
}
diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp
index 134002cf33..85c91a592a 100644
--- a/src/qml/qml/qqmlcustomparser.cpp
+++ b/src/qml/qml/qqmlcustomparser.cpp
@@ -39,7 +39,6 @@
#include "qqmlcustomparser_p.h"
-#include "qqmlcompiler_p.h"
#include <private/qqmltypecompiler_p.h>
#include <QtCore/qdebug.h>
@@ -101,11 +100,7 @@ void QQmlCustomParser::clearErrors()
*/
void QQmlCustomParser::error(const QV4::CompiledData::Location &location, const QString &description)
{
- QQmlError error;
- error.setLine(location.line);
- error.setColumn(location.column);
- error.setDescription(description);
- exceptions << error;
+ exceptions << QQmlCompileError(location, description);
}
struct StaticQtMetaObject : public QObject
@@ -166,11 +161,13 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
*/
const QMetaObject *QQmlCustomParser::resolveType(const QString& name) const
{
+ if (!imports.isT1())
+ return nullptr;
QQmlType *qmltype = 0;
- if (!validator->imports().resolveType(name, &qmltype, 0, 0, 0))
- return 0;
+ if (!imports.asT1()->resolveType(name, &qmltype, 0, 0, 0))
+ return nullptr;
if (!qmltype)
- return 0;
+ return nullptr;
return qmltype->metaObject();
}
diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h
index 9aa052c1ad..5eb409990d 100644
--- a/src/qml/qml/qqmlcustomparser_p.h
+++ b/src/qml/qml/qqmlcustomparser_p.h
@@ -54,13 +54,13 @@
#include "qqmlmetatype_p.h"
#include "qqmlerror.h"
#include "qqmlbinding_p.h"
+#include <private/qqmltypecompiler_p.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qxmlstream.h>
QT_BEGIN_NAMESPACE
-class QQmlCompiledData;
class QQmlPropertyValidator;
class QQmlEnginePrivate;
@@ -84,7 +84,7 @@ public:
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) = 0;
virtual void applyBindings(QObject *, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &) = 0;
- QList<QQmlError> errors() const { return exceptions; }
+ QVector<QQmlCompileError> errors() const { return exceptions; }
protected:
void error(const QV4::CompiledData::Binding *binding, const QString& description)
@@ -98,7 +98,7 @@ protected:
const QMetaObject *resolveType(const QString&) const;
private:
- QList<QQmlError> exceptions;
+ QVector<QQmlCompileError> exceptions;
QQmlEnginePrivate *engine;
const QQmlPropertyValidator *validator;
Flags m_flags;
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index ad2456a68d..dce75c51aa 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -53,7 +53,7 @@
#include <private/qtqmlglobal_p.h>
#include <private/qobject_p.h>
-
+#include <private/qqmlpropertyindex_p.h>
#include <private/qv4value_p.h>
#include <private/qv4persistent_p.h>
#include <qjsengine.h>
@@ -63,7 +63,6 @@ QT_BEGIN_NAMESPACE
template <class Key, class T> class QHash;
class QQmlEngine;
class QQmlGuardImpl;
-class QQmlCompiledData;
class QQmlAbstractBinding;
class QQmlBoundSignal;
class QQmlContext;
@@ -72,6 +71,13 @@ class QQmlContextData;
class QQmlNotifier;
class QQmlDataExtended;
class QQmlNotifierEndpoint;
+
+namespace QV4 {
+namespace CompiledData {
+struct CompilationUnit;
+}
+}
+
// This class is structured in such a way, that simply zero'ing it is the
// default state for elemental object allocations. This is crucial in the
// workings of the QQmlInstruction::CreateSimpleObject instruction.
@@ -123,14 +129,16 @@ public:
quint32 parentFrozen:1;
quint32 dummy:21;
- // When bindingBitsSize < 32, we store the binding bit flags inside
- // bindingBitsValue. When we need more than 32 bits, we allocated
+ // When bindingBitsSize < sizeof(ptr), we store the binding bit flags inside
+ // bindingBitsValue. When we need more than sizeof(ptr) bits, we allocated
// sufficient space and use bindingBits to point to it.
int bindingBitsSize;
+ typedef quintptr BindingBitsType;
union {
- quint32 *bindingBits;
- quint32 bindingBitsValue;
+ BindingBitsType *bindingBits;
+ BindingBitsType bindingBitsValue;
};
+ enum { MaxInlineBits = sizeof(BindingBitsType) * 8 };
struct NotifyList {
quint64 connectionMask;
@@ -168,7 +176,7 @@ public:
void clearBindingBit(int);
void setBindingBit(QObject *obj, int);
- inline bool hasPendingBindingBit(int) const;
+ inline bool hasPendingBindingBit(int index) const;
void setPendingBindingBit(QObject *obj, int);
void clearPendingBindingBit(int);
@@ -179,10 +187,10 @@ public:
struct DeferredData {
unsigned int deferredIdx;
- QQmlCompiledData *compiledData;//Not always the same as the other compiledData
+ QV4::CompiledData::CompilationUnit *compilationUnit;//Not always the same as the other compilation unit
QQmlContextData *context;//Could be either context or outerContext
};
- QQmlCompiledData *compiledData;
+ QV4::CompiledData::CompilationUnit *compilationUnit;
DeferredData *deferredData;
QV4::WeakValue jsWrapper;
@@ -221,15 +229,26 @@ public:
static void markAsDeleted(QObject *);
static void setQueuedForDeletion(QObject *);
- static inline void flushPendingBinding(QObject *, int coreIndex);
+ static inline void flushPendingBinding(QObject *, QQmlPropertyIndex propertyIndex);
- static void ensurePropertyCache(QJSEngine *engine, QObject *object);
+ static QQmlPropertyCache *ensurePropertyCache(QJSEngine *engine, QObject *object);
private:
// For attachedProperties
mutable QQmlDataExtended *extendedData;
- void flushPendingBindingImpl(int coreIndex);
+ void flushPendingBindingImpl(QQmlPropertyIndex index);
+
+ Q_ALWAYS_INLINE bool hasBitSet(int bit) const
+ {
+ if (bindingBitsSize <= bit)
+ return false;
+
+ if (bindingBitsSize == MaxInlineBits)
+ return bindingBitsValue & (BindingBitsType(1) << bit);
+ else
+ return bindingBits[bit / MaxInlineBits] & (BindingBitsType(1) << (bit % MaxInlineBits));
+ }
};
bool QQmlData::wasDeleted(QObject *object)
@@ -275,27 +294,25 @@ inline bool QQmlData::signalHasEndpoint(int index) const
bool QQmlData::hasBindingBit(int coreIndex) const
{
- int bit = coreIndex * 2;
+ Q_ASSERT(coreIndex >= 0);
+ Q_ASSERT(coreIndex <= 0xffff);
- return bindingBitsSize > bit &&
- ((bindingBitsSize == 32) ? (bindingBitsValue & (1 << bit)) :
- (bindingBits[bit / 32] & (1 << (bit % 32))));
+ return hasBitSet(coreIndex * 2);
}
bool QQmlData::hasPendingBindingBit(int coreIndex) const
{
- int bit = coreIndex * 2 + 1;
+ Q_ASSERT(coreIndex >= 0);
+ Q_ASSERT(coreIndex <= 0xffff);
- return bindingBitsSize > bit &&
- ((bindingBitsSize == 32) ? (bindingBitsValue & (1 << bit)) :
- (bindingBits[bit / 32] & (1 << (bit % 32))));
+ return hasBitSet(coreIndex * 2 + 1);
}
-void QQmlData::flushPendingBinding(QObject *o, int coreIndex)
+void QQmlData::flushPendingBinding(QObject *o, QQmlPropertyIndex propertyIndex)
{
QQmlData *data = QQmlData::get(o, false);
- if (data && data->hasPendingBindingBit(coreIndex))
- data->flushPendingBindingImpl(coreIndex);
+ if (data && data->hasPendingBindingBit(propertyIndex.coreIndex()))
+ data->flushPendingBindingImpl(propertyIndex);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmldelayedcallqueue.cpp b/src/qml/qml/qqmldelayedcallqueue.cpp
index b3a0baffb4..d10a8c7718 100644
--- a/src/qml/qml/qqmldelayedcallqueue.cpp
+++ b/src/qml/qml/qqmldelayedcallqueue.cpp
@@ -74,7 +74,7 @@ void QQmlDelayedCallQueue::DelayedFunctionCall::execute(QV4::ExecutionEngine *en
const QV4::FunctionObject *callback = m_function.as<QV4::FunctionObject>();
Q_ASSERT(callback);
- callback->call(callData);
+ callback->call(scope, callData);
if (scope.engine->hasException) {
QQmlError error = scope.engine->catchExceptionAsQmlError();
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index fd1795499e..daa12fae26 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -42,7 +42,6 @@
#include "qqmlcomponentattached_p.h"
#include "qqmlcontext_p.h"
-#include "qqmlcompiler_p.h"
#include "qqml.h"
#include "qqmlcontext.h"
#include "qqmlexpression.h"
@@ -58,7 +57,6 @@
#include "qqmllist_p.h"
#include "qqmltypenamecache_p.h"
#include "qqmlnotifier_p.h"
-#include <private/qqmldebugconnector_p.h>
#include "qqmlincubator.h"
#include "qqmlabstracturlinterceptor.h"
#include <private/qqmlboundsignal_p.h>
@@ -91,6 +89,7 @@
#include <private/qqmlobjectmodel_p.h>
#include <private/qquickworkerscript_p.h>
#include <private/qqmlinstantiator_p.h>
+#include <private/qqmlloggingcategory_p.h>
#ifdef Q_OS_WIN // for %APPDATA%
# include <qt_windows.h>
@@ -107,6 +106,9 @@ Q_DECLARE_METATYPE(QQmlProperty)
QT_BEGIN_NAMESPACE
+typedef QQmlData::BindingBitsType BindingBitsType;
+enum { MaxInlineBits = QQmlData::MaxInlineBits };
+
void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
{
QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
@@ -114,6 +116,39 @@ void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
QQmlValueTypeFactory::registerValueTypes(uri, versionMajor, versionMinor);
}
+// Declared in qqml.h
+int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject,
+ const char *uri, int versionMajor,
+ int versionMinor, const char *qmlName,
+ const QString& reason)
+{
+ QQmlPrivate::RegisterType type = {
+ 0,
+
+ 0,
+ 0,
+ 0,
+ Q_NULLPTR,
+ reason,
+
+ uri, versionMajor, versionMinor, qmlName, &staticMetaObject,
+
+ QQmlAttachedPropertiesFunc(),
+ Q_NULLPTR,
+
+ 0,
+ 0,
+ 0,
+
+ Q_NULLPTR, Q_NULLPTR,
+
+ Q_NULLPTR,
+ 0
+ };
+
+ return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
+}
+
/*!
\qmltype QtObject
\instantiates QObject
@@ -186,6 +221,7 @@ void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int
qmlRegisterType<QQmlInstantiator>(uri, versionMajor, (versionMinor < 1 ? 1 : versionMinor), "Instantiator"); //Only available in >=2.1
qmlRegisterCustomType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections", new QQmlConnectionsParser);
qmlRegisterType<QQmlInstanceModel>();
+ qmlRegisterType<QQmlLoggingCategory>(uri, versionMajor, (versionMinor < 8 ? 8 : versionMinor), "LoggingCategory"); //Only available in >=2.8
}
@@ -404,11 +440,10 @@ The following functions are also on the Qt object.
\li \c "ios" - iOS
\li \c "tvos" - tvOS
\li \c "linux" - Linux
- \li \c "osx" - OS X
+ \li \c "osx" - \macos
\li \c "unix" - Other Unix-based OS
\li \c "windows" - Windows
- \li \c "wince" - Windows CE
- \li \c "winrt" - Windows RT
+ \li \c "winrt" - Windows Runtime
\li \c "winphone" - Windows Phone
\endlist
\endtable
@@ -519,6 +554,18 @@ The following functions are also on the Qt object.
\li This read-only property can be used to determine whether or not the
platform supports multiple windows. Some embedded platforms do not support
multiple windows, for example.
+
+ \row
+ \li \c application.screens
+ \li An array containing the descriptions of all connected screens. The
+ elements of the array are objects with the same properties as the
+ \l{Screen} attached object. In practice the array corresponds to the screen
+ list returned by QGuiApplication::screens(). In addition to examining
+ properties like name, width, height, etc., the array elements can also be
+ assigned to the targetScreen property of Window items, thus serving as an
+ alternative to the C++ side's QWindow::setScreen(). This property has been
+ added in Qt 5.9.
+
\endtable
The object also has one signal, aboutToQuit(), which is the same as \l QCoreApplication::aboutToQuit().
@@ -535,6 +582,8 @@ The following functions are also on the Qt object.
\li application.layoutDirection
\li application.font
\endlist
+
+ \sa Screen, Window, Window.targetScreen
*/
/*!
@@ -604,7 +653,10 @@ the same object as is returned from the Qt.include() call.
QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
: propertyCapture(0), rootContext(0),
- profiler(0), outputWarningsToMsgLog(true),
+#ifndef QT_NO_QML_DEBUGGER
+ profiler(0),
+#endif
+ outputWarningsToMsgLog(true),
cleanup(0), erroredBindings(0), inProgressCreations(0),
workerScriptEngine(0),
activeObjectCreator(0),
@@ -619,7 +671,6 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
QQmlEnginePrivate::~QQmlEnginePrivate()
{
typedef QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::const_iterator TypePropertyCacheIt;
- typedef QHash<int, QQmlCompiledData *>::const_iterator CompositeTypesIt;
if (inProgressCreations)
qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
@@ -640,7 +691,7 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
for (TypePropertyCacheIt iter = typePropertyCache.cbegin(), end = typePropertyCache.cend(); iter != end; ++iter)
(*iter)->release();
- for (CompositeTypesIt iter = m_compositeTypes.cbegin(), end = m_compositeTypes.cend(); iter != end; ++iter) {
+ for (auto iter = m_compositeTypes.cbegin(), end = m_compositeTypes.cend(); iter != end; ++iter) {
iter.value()->isRegisteredWithEngine = false;
// since unregisterInternalCompositeType() will not be called in this
@@ -648,12 +699,9 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
QMetaType::unregisterType(iter.value()->metaTypeId);
QMetaType::unregisterType(iter.value()->listMetaTypeId);
}
+#ifndef QT_NO_QML_DEBUGGER
delete profiler;
-}
-
-void QQmlEnginePrivate::enableProfiler()
-{
- profiler = new QQmlProfiler();
+#endif
}
void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
@@ -680,9 +728,10 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
QQmlData::QQmlData()
: ownedByQml1(false), ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false),
hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false),
- hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false), bindingBitsSize(0), bindingBits(0), notifyList(0), context(0), outerContext(0),
+ hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false),
+ bindingBitsSize(MaxInlineBits), bindingBitsValue(0), notifyList(0), context(0), outerContext(0),
bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0),
- lineNumber(0), columnNumber(0), jsEngineId(0), compiledData(0), deferredData(0),
+ lineNumber(0), columnNumber(0), jsEngineId(0), compilationUnit(0), deferredData(0),
propertyCache(0), guards(0), extendedData(0)
{
init();
@@ -840,18 +889,20 @@ void QQmlData::setQueuedForDeletion(QObject *object)
}
}
-void QQmlData::flushPendingBindingImpl(int coreIndex)
+void QQmlData::flushPendingBindingImpl(QQmlPropertyIndex index)
{
- clearPendingBindingBit(coreIndex);
+ clearPendingBindingBit(index.coreIndex());
// Find the binding
QQmlAbstractBinding *b = bindings;
- while (b && b->targetPropertyIndex() != coreIndex)
+ while (b && (b->targetPropertyIndex().coreIndex() != index.coreIndex() ||
+ b->targetPropertyIndex().hasValueTypeIndex()))
b = b->nextBinding();
- if (b && b->targetPropertyIndex() == coreIndex)
- b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::DontRemoveBinding);
+ if (b && b->targetPropertyIndex().coreIndex() == index.coreIndex() &&
+ !b->targetPropertyIndex().hasValueTypeIndex())
+ b->setEnabled(true, QQmlPropertyData::BypassInterceptor |
+ QQmlPropertyData::DontRemoveBinding);
}
bool QQmlEnginePrivate::baseModulesUninitialized = true;
@@ -969,8 +1020,8 @@ QQmlEngine::~QQmlEngine()
// we do this here and not in the private dtor since otherwise a crash can
// occur (if we are the QObject parent of the QObject singleton instance)
// XXX TODO: performance -- store list of singleton types separately?
- QList<QQmlType*> singletonTypes = QQmlMetaType::qmlSingletonTypes();
- foreach (QQmlType *currType, singletonTypes)
+ const QList<QQmlType*> singletonTypes = QQmlMetaType::qmlSingletonTypes();
+ for (QQmlType *currType : singletonTypes)
currType->singletonInstanceInfo()->destroy(this);
delete d->rootContext;
@@ -979,8 +1030,19 @@ QQmlEngine::~QQmlEngine()
/*! \fn void QQmlEngine::quit()
This signal is emitted when the QML loaded by the engine would like to quit.
+
+ \sa exit()
*/
+/*! \fn void QQmlEngine::exit(int retCode)
+ This signal is emitted when the QML loaded by the engine would like to exit
+ from the event loop with the specified return code.
+
+ \since 5.8
+ \sa quit()
+ */
+
+
/*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
This signal is emitted when \a warnings messages are generated by QML.
*/
@@ -1411,7 +1473,7 @@ void qmlExecuteDeferred(QObject *object)
QQmlComponentPrivate::beginDeferred(ep, object, &state);
// Release the reference for the deferral action (we still have one from construction)
- data->deferredData->compiledData->release();
+ data->deferredData->compilationUnit->release();
delete data->deferredData;
data->deferredData = 0;
@@ -1642,13 +1704,13 @@ void QQmlData::destroyed(QObject *object)
if (bindings && !bindings->ref.deref())
delete bindings;
- if (compiledData) {
- compiledData->release();
- compiledData = 0;
+ if (compilationUnit) {
+ compilationUnit->release();
+ compilationUnit = 0;
}
if (deferredData) {
- deferredData->compiledData->release();
+ deferredData->compilationUnit->release();
delete deferredData;
deferredData = 0;
}
@@ -1671,7 +1733,7 @@ void QQmlData::destroyed(QObject *object)
QString source = expr->expression();
if (source.size() > 100) {
source.truncate(96);
- source.append(QStringLiteral(" ..."));
+ source.append(QLatin1String(" ..."));
}
locationString.append(source);
} else {
@@ -1691,7 +1753,7 @@ void QQmlData::destroyed(QObject *object)
signalHandler = next;
}
- if (bindingBitsSize > 32)
+ if (bindingBitsSize > MaxInlineBits)
free(bindingBits);
if (propertyCache)
@@ -1716,6 +1778,8 @@ void QQmlData::destroyed(QObject *object)
if (ownMemory)
delete this;
+ else
+ this->~QQmlData();
}
DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
@@ -1739,31 +1803,27 @@ void QQmlData::parentChanged(QObject *object, QObject *parent)
static void QQmlData_setBit(QQmlData *data, QObject *obj, int bit)
{
- if (data->bindingBitsSize == 0 && bit < 32) {
- data->bindingBitsSize = 32;
- }
-
- if (data->bindingBitsSize <= bit) {
+ if (Q_UNLIKELY(data->bindingBitsSize <= bit)) {
int props = QQmlMetaObject(obj).propertyCount();
Q_ASSERT(bit < 2 * props);
- int arraySize = (2 * props + 31) / 32;
+ int arraySize = (2 * props + MaxInlineBits - 1) / MaxInlineBits;
Q_ASSERT(arraySize > 1);
// special handling for 32 here is to make sure we wipe the first byte
// when going from bindingBitsValue to bindingBits, and preserve the old
// set bits so we can restore them after the allocation
- int oldArraySize = data->bindingBitsSize > 32 ? data->bindingBitsSize / 32 : 0;
- quint32 oldValue = data->bindingBitsSize == 32 ? data->bindingBitsValue : 0;
+ int oldArraySize = data->bindingBitsSize > MaxInlineBits ? data->bindingBitsSize / MaxInlineBits : 0;
+ quintptr oldValue = data->bindingBitsSize == MaxInlineBits ? data->bindingBitsValue : 0;
- data->bindingBits = (quint32 *)realloc((data->bindingBitsSize == 32) ? 0 : data->bindingBits,
- arraySize * sizeof(quint32));
+ data->bindingBits = static_cast<BindingBitsType *>(realloc((data->bindingBitsSize == MaxInlineBits) ? 0 : data->bindingBits,
+ arraySize * sizeof(BindingBitsType)));
memset(data->bindingBits + oldArraySize,
0x00,
- sizeof(quint32) * (arraySize - oldArraySize));
+ sizeof(BindingBitsType) * (arraySize - oldArraySize));
- data->bindingBitsSize = arraySize * 32;
+ data->bindingBitsSize = arraySize * MaxInlineBits;
// reinstate bindingBitsValue after we dropped it
if (oldValue) {
@@ -1771,50 +1831,60 @@ static void QQmlData_setBit(QQmlData *data, QObject *obj, int bit)
}
}
- if (data->bindingBitsSize == 32)
- data->bindingBitsValue |= (1 << (bit % 32));
+ if (data->bindingBitsSize == MaxInlineBits)
+ data->bindingBitsValue |= BindingBitsType(1) << bit;
else
- data->bindingBits[bit / 32] |= (1 << (bit % 32));
+ data->bindingBits[bit / MaxInlineBits] |= (BindingBitsType(1) << (bit % MaxInlineBits));
}
static void QQmlData_clearBit(QQmlData *data, int bit)
{
if (data->bindingBitsSize > bit) {
- if (data->bindingBitsSize == 32)
- data->bindingBitsValue &= ~(1 << (bit % 32));
+ if (data->bindingBitsSize == MaxInlineBits)
+ data->bindingBitsValue &= ~(BindingBitsType(1) << (bit % MaxInlineBits));
else
- data->bindingBits[bit / 32] &= ~(1 << (bit % 32));
+ data->bindingBits[bit / MaxInlineBits] &= ~(BindingBitsType(1) << (bit % MaxInlineBits));
}
}
void QQmlData::clearBindingBit(int coreIndex)
{
+ Q_ASSERT(coreIndex >= 0);
+ Q_ASSERT(coreIndex <= 0xffff);
QQmlData_clearBit(this, coreIndex * 2);
}
void QQmlData::setBindingBit(QObject *obj, int coreIndex)
{
+ Q_ASSERT(coreIndex >= 0);
+ Q_ASSERT(coreIndex <= 0xffff);
QQmlData_setBit(this, obj, coreIndex * 2);
}
void QQmlData::clearPendingBindingBit(int coreIndex)
{
+ Q_ASSERT(coreIndex >= 0);
+ Q_ASSERT(coreIndex <= 0xffff);
QQmlData_clearBit(this, coreIndex * 2 + 1);
}
void QQmlData::setPendingBindingBit(QObject *obj, int coreIndex)
{
+ Q_ASSERT(coreIndex >= 0);
+ Q_ASSERT(coreIndex <= 0xffff);
QQmlData_setBit(this, obj, coreIndex * 2 + 1);
}
-void QQmlData::ensurePropertyCache(QJSEngine *engine, QObject *object)
+QQmlPropertyCache *QQmlData::ensurePropertyCache(QJSEngine *engine, QObject *object)
{
Q_ASSERT(engine);
QQmlData *ddata = QQmlData::get(object, /*create*/true);
- if (ddata->propertyCache)
- return;
- ddata->propertyCache = QJSEnginePrivate::get(engine)->cache(object);
- if (ddata->propertyCache) ddata->propertyCache->addref();
+ if (!ddata->propertyCache) {
+ ddata->propertyCache = QJSEnginePrivate::get(engine)->cache(object);
+ if (ddata->propertyCache)
+ ddata->propertyCache->addref();
+ }
+ return ddata->propertyCache;
}
void QQmlEnginePrivate::sendQuit()
@@ -1826,6 +1896,14 @@ void QQmlEnginePrivate::sendQuit()
}
}
+void QQmlEnginePrivate::sendExit(int retCode)
+{
+ Q_Q(QQmlEngine);
+ if (q->receivers(SIGNAL(exit(int))) == 0)
+ qWarning("Signal QQmlEngine::exit() emitted, but no receivers connected to handle it.");
+ emit q->exit(retCode);
+}
+
static void dumpwarning(const QQmlError &error)
{
QMessageLogger(error.url().toString().toLatin1().constData(),
@@ -2225,9 +2303,9 @@ int QQmlEnginePrivate::listType(int t) const
QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
{
Locker locker(this);
- QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.constFind(t);
+ auto iter = m_compositeTypes.constFind(t);
if (iter != m_compositeTypes.cend()) {
- return QQmlMetaObject((*iter)->compilationUnit->rootPropertyCache());
+ return QQmlMetaObject((*iter)->rootPropertyCache());
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
return QQmlMetaObject(type?type->baseMetaObject():0);
@@ -2237,9 +2315,9 @@ QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
{
Locker locker(this);
- QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.constFind(t);
+ auto iter = m_compositeTypes.constFind(t);
if (iter != m_compositeTypes.cend()) {
- return QQmlMetaObject((*iter)->compilationUnit->rootPropertyCache());
+ return QQmlMetaObject((*iter)->rootPropertyCache());
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
return QQmlMetaObject(type?type->metaObject():0);
@@ -2249,9 +2327,9 @@ QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
{
Locker locker(this);
- QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constFind(t);
+ auto iter = m_compositeTypes.constFind(t);
if (iter != m_compositeTypes.cend()) {
- return (*iter)->compilationUnit->rootPropertyCache();
+ return (*iter)->rootPropertyCache();
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
locker.unlock();
@@ -2262,9 +2340,9 @@ QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
{
Locker locker(this);
- QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constFind(t);
+ auto iter = m_compositeTypes.constFind(t);
if (iter != m_compositeTypes.cend()) {
- return (*iter)->compilationUnit->rootPropertyCache();
+ return (*iter)->rootPropertyCache();
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
locker.unlock();
@@ -2272,9 +2350,9 @@ QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
}
}
-void QQmlEnginePrivate::registerInternalCompositeType(QQmlCompiledData *data)
+void QQmlEnginePrivate::registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit)
{
- QByteArray name = data->compilationUnit->rootPropertyCache()->className();
+ QByteArray name = compilationUnit->rootPropertyCache()->className();
QByteArray ptr = name + '*';
QByteArray lst = "QQmlListProperty<" + name + '>';
@@ -2292,21 +2370,21 @@ void QQmlEnginePrivate::registerInternalCompositeType(QQmlCompiledData *data)
static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
static_cast<QMetaObject*>(0));
- data->metaTypeId = ptr_type;
- data->listMetaTypeId = lst_type;
- data->isRegisteredWithEngine = true;
+ compilationUnit->metaTypeId = ptr_type;
+ compilationUnit->listMetaTypeId = lst_type;
+ compilationUnit->isRegisteredWithEngine = true;
Locker locker(this);
m_qmlLists.insert(lst_type, ptr_type);
// The QQmlCompiledData is not referenced here, but it is removed from this
// hash in the QQmlCompiledData destructor
- m_compositeTypes.insert(ptr_type, data);
+ m_compositeTypes.insert(ptr_type, compilationUnit);
}
-void QQmlEnginePrivate::unregisterInternalCompositeType(QQmlCompiledData *data)
+void QQmlEnginePrivate::unregisterInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit)
{
- int ptr_type = data->metaTypeId;
- int lst_type = data->listMetaTypeId;
+ int ptr_type = compilationUnit->metaTypeId;
+ int lst_type = compilationUnit->listMetaTypeId;
Locker locker(this);
m_qmlLists.remove(lst_type);
diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h
index 132af78f80..3111d1013e 100644
--- a/src/qml/qml/qqmlengine.h
+++ b/src/qml/qml/qqmlengine.h
@@ -151,10 +151,11 @@ public:
static ObjectOwnership objectOwnership(QObject *);
protected:
QQmlEngine(QQmlEnginePrivate &dd, QObject *p);
- virtual bool event(QEvent *);
+ bool event(QEvent *) override;
Q_SIGNALS:
void quit();
+ void exit(int retCode);
void warnings(const QList<QQmlError> &warnings);
private:
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 18bee387dd..713b03dbf3 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -134,8 +134,12 @@ public:
QRecyclePool<QQmlJavaScriptExpressionGuard> jsExpressionGuardPool;
QQmlContext *rootContext;
+
+#ifdef QT_NO_QML_DEBUGGER
+ static const quintptr profiler = 0;
+#else
QQmlProfiler *profiler;
- void enableProfiler();
+#endif
bool outputWarningsToMsgLog;
@@ -216,13 +220,14 @@ public:
QQmlMetaObject metaObjectForType(int) const;
QQmlPropertyCache *propertyCacheForType(int);
QQmlPropertyCache *rawPropertyCacheForType(int);
- void registerInternalCompositeType(QQmlCompiledData *);
- void unregisterInternalCompositeType(QQmlCompiledData *);
+ void registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit);
+ void unregisterInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit);
bool isTypeLoaded(const QUrl &url) const;
bool isScriptLoaded(const QUrl &url) const;
void sendQuit();
+ void sendExit(int retCode = 0);
void warning(const QQmlError &);
void warning(const QList<QQmlError> &);
void warning(QQmlDelayedError *);
@@ -260,7 +265,7 @@ private:
// the threaded loader. Only access them through their respective accessor methods.
QHash<QPair<QQmlType *, int>, QQmlPropertyCache *> typePropertyCache;
QHash<int, int> m_qmlLists;
- QHash<int, QQmlCompiledData *> m_compositeTypes;
+ QHash<int, QV4::CompiledData::CompilationUnit *> m_compositeTypes;
static bool s_designerMode;
// These members is protected by the full QQmlEnginePrivate::mutex mutex
diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp
index 74ceeabeb4..b309550ca8 100644
--- a/src/qml/qml/qqmlerror.cpp
+++ b/src/qml/qml/qqmlerror.cpp
@@ -249,9 +249,9 @@ QString QQmlError::toString() const
int l(line());
if (u.isEmpty() || (u.isLocalFile() && u.path().isEmpty()))
- rv = QLatin1String("<Unknown File>");
+ rv += QLatin1String("<Unknown File>");
else
- rv = u.toString();
+ rv += u.toString();
if (l != -1) {
rv += QLatin1Char(':') + QString::number(l);
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index 50880e70ea..6afbd05e3e 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -44,7 +44,7 @@
#include "qqmlengine_p.h"
#include "qqmlcontext_p.h"
#include "qqmlscriptstring_p.h"
-#include "qqmlcompiler_p.h"
+#include "qqmlbinding_p.h"
#include <private/qv8engine_p.h>
#include <QtCore/qdebug.h>
@@ -245,14 +245,15 @@ void QQmlExpression::setExpression(const QString &expression)
}
// Must be called with a valid handle scope
-QV4::ReturnedValue QQmlExpressionPrivate::v4value(bool *isUndefined)
+void QQmlExpressionPrivate::v4value(bool *isUndefined, QV4::Scope &scope)
{
if (!expressionFunctionValid) {
createQmlBinding(context(), scopeObject(), expression, url, line);
expressionFunctionValid = true;
}
- return evaluate(isUndefined);
+ QV4::ScopedCallData callData(scope);
+ evaluate(callData, isUndefined, scope);
}
QVariant QQmlExpressionPrivate::value(bool *isUndefined)
@@ -271,9 +272,9 @@ QVariant QQmlExpressionPrivate::value(bool *isUndefined)
{
QV4::Scope scope(QV8Engine::getV4(ep->v8engine()));
- QV4::ScopedValue result(scope, v4value(isUndefined));
+ v4value(isUndefined, scope);
if (!hasError())
- rv = scope.engine->toVariant(result, -1);
+ rv = scope.engine->toVariant(scope.result, -1);
}
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
diff --git a/src/qml/qml/qqmlexpression_p.h b/src/qml/qml/qqmlexpression_p.h
index ccc629a3a3..81a749e017 100644
--- a/src/qml/qml/qqmlexpression_p.h
+++ b/src/qml/qml/qqmlexpression_p.h
@@ -56,7 +56,6 @@
#include <private/qqmlengine_p.h>
#include <private/qfieldlist_p.h>
#include <private/qflagpointer_p.h>
-#include <private/qdeletewatcher_p.h>
#include <private/qqmljavascriptexpression_p.h>
QT_BEGIN_NAMESPACE
@@ -76,7 +75,7 @@ public:
QVariant value(bool *isUndefined = 0);
- QV4::ReturnedValue v4value(bool *isUndefined = 0);
+ void v4value(bool *isUndefined, QV4::Scope &scope);
static inline QQmlExpressionPrivate *get(QQmlExpression *expr);
static inline QQmlExpression *get(QQmlExpressionPrivate *expr);
@@ -86,8 +85,8 @@ public:
bool expressionFunctionValid:1;
// Inherited from QQmlJavaScriptExpression
- virtual QString expressionIdentifier();
- virtual void expressionChanged();
+ QString expressionIdentifier() override;
+ void expressionChanged() override;
QString expression;
diff --git a/src/qml/qml/qqmlextensionplugin.h b/src/qml/qml/qqmlextensionplugin.h
index de482d0352..934cf0f51a 100644
--- a/src/qml/qml/qqmlextensionplugin.h
+++ b/src/qml/qml/qqmlextensionplugin.h
@@ -64,7 +64,7 @@ public:
QUrl baseUrl() const;
virtual void registerTypes(const char *uri) = 0;
- virtual void initializeEngine(QQmlEngine *engine, const char *uri);
+ void initializeEngine(QQmlEngine *engine, const char *uri) override;
private:
Q_DISABLE_COPY(QQmlExtensionPlugin)
diff --git a/src/qml/qml/qqmlfileselector_p.h b/src/qml/qml/qqmlfileselector_p.h
index 57ef194c10..a7360f83d9 100644
--- a/src/qml/qml/qqmlfileselector_p.h
+++ b/src/qml/qml/qqmlfileselector_p.h
@@ -80,7 +80,7 @@ public:
QQmlFileSelectorInterceptor(QQmlFileSelectorPrivate* pd);
QQmlFileSelectorPrivate* d;
protected:
- virtual QUrl intercept(const QUrl &path, DataType type);
+ QUrl intercept(const QUrl &path, DataType type) override;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 01f1042de4..4c5179dc75 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -229,7 +229,7 @@ public:
};
QList<Import *> imports;
- Import *findImport(const QString &uri);
+ Import *findImport(const QString &uri) const;
bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type,
int *vmajor, int *vminor, QQmlType** type_return,
@@ -399,9 +399,7 @@ bool excludeBaseUrl(const QString &importUrl, const QString &fileName, const QSt
if (baseUrl.startsWith(importUrl))
{
- QString typeUrl(importUrl);
- typeUrl.append(fileName);
- if (typeUrl == baseUrl)
+ if (fileName == baseUrl.midRef(importUrl.size()))
return false;
}
@@ -455,7 +453,7 @@ QList<QQmlImports::ScriptReference> QQmlImports::resolvedScripts() const
for (int ii = set.imports.count() - 1; ii >= 0; --ii) {
const QQmlImportNamespace::Import *import = set.imports.at(ii);
- foreach (const QQmlDirParser::Script &script, import->qmlDirScripts) {
+ for (const QQmlDirParser::Script &script : import->qmlDirScripts) {
ScriptReference ref;
ref.nameSpace = script.nameSpace;
ref.location = QUrl(import->url).resolved(QUrl(script.fileName));
@@ -469,7 +467,7 @@ QList<QQmlImports::ScriptReference> QQmlImports::resolvedScripts() const
for (int ii = set.imports.count() - 1; ii >= 0; --ii) {
const QQmlImportNamespace::Import *import = set.imports.at(ii);
- foreach (const QQmlDirParser::Script &script, import->qmlDirScripts) {
+ for (const QQmlDirParser::Script &script : import->qmlDirScripts) {
ScriptReference ref;
ref.nameSpace = script.nameSpace;
ref.qualifier = set.prefix;
@@ -540,10 +538,10 @@ QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version)
{
if (version == QQmlImports::FullyVersioned) {
// extension with fully encoded version number (eg. MyModule.3.2)
- return QString(QLatin1String(".%1.%2")).arg(vmaj).arg(vmin);
+ return QString::asprintf(".%d.%d", vmaj, vmin);
} else if (version == QQmlImports::PartiallyVersioned) {
// extension with encoded version major (eg. MyModule.3)
- return QString(QLatin1String(".%1")).arg(vmaj);
+ return QString::asprintf(".%d", vmaj);
} // else extension without version number (eg. MyModule)
return QString();
}
@@ -786,14 +784,13 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor,
return false;
}
-QQmlImportNamespace::Import *QQmlImportNamespace::findImport(const QString &uri)
+QQmlImportNamespace::Import *QQmlImportNamespace::findImport(const QString &uri) const
{
- for (QList<Import *>::iterator it = imports.begin(), end = imports.end(); it != end; ++it) {
- if ((*it)->uri == uri)
- return *it;
+ for (Import *import : imports) {
+ if (import->uri == uri)
+ return import;
}
-
- return 0;
+ return nullptr;
}
bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type,
@@ -900,6 +897,21 @@ static QStringList versionUriList(const QString &uri, int vmaj, int vmin)
}
#ifndef QT_NO_LIBRARY
+static QVector<QStaticPlugin> makePlugins()
+{
+ QVector<QStaticPlugin> plugins;
+ // To avoid traversing all static plugins for all imports, we cut down
+ // the list the first time called to only contain QML plugins:
+ const auto staticPlugins = QPluginLoader::staticPlugins();
+ for (const QStaticPlugin &plugin : staticPlugins) {
+ if (plugin.metaData().value(QLatin1String("IID")).toString()
+ == QLatin1String(QQmlExtensionInterface_iid)) {
+ plugins.append(plugin);
+ }
+ }
+ return plugins;
+}
+
/*!
Get all static plugins that are QML plugins and has a meta data URI that matches with one of
\a versionUris, which is a list of all possible versioned URI combinations - see versionUriList()
@@ -908,20 +920,11 @@ static QStringList versionUriList(const QString &uri, int vmaj, int vmin)
bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri, const QStringList &versionUris,
const QString &qmldirPath, QList<QQmlError> *errors)
{
- static QVector<QStaticPlugin> plugins;
- if (plugins.isEmpty()) {
- // To avoid traversing all static plugins for all imports, we cut down
- // the list the first time called to only contain QML plugins:
- foreach (const QStaticPlugin &plugin, QPluginLoader::staticPlugins()) {
- if (plugin.metaData().value(QStringLiteral("IID")).toString() == QLatin1String(QQmlExtensionInterface_iid))
- plugins.append(plugin);
- }
- }
-
- foreach (const QStaticPlugin &plugin, plugins) {
+ static const QVector<QStaticPlugin> plugins = makePlugins();
+ for (const QStaticPlugin &plugin : plugins) {
// Since a module can list more than one plugin, we keep iterating even after we found a match.
if (QQmlExtensionPlugin *instance = qobject_cast<QQmlExtensionPlugin *>(plugin.instance())) {
- const QJsonArray metaTagsUriList = plugin.metaData().value(QStringLiteral("uri")).toArray();
+ const QJsonArray metaTagsUriList = plugin.metaData().value(QLatin1String("uri")).toArray();
if (metaTagsUriList.isEmpty()) {
if (errors) {
QQmlError error;
@@ -933,7 +936,7 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &res
return false;
}
// A plugin can be set up to handle multiple URIs, so go through the list:
- foreach (const QJsonValue &metaTagUri, metaTagsUriList) {
+ for (const QJsonValue &metaTagUri : metaTagsUriList) {
if (versionUris.contains(metaTagUri.toString())) {
result.append(qMakePair(plugin, metaTagsUriList));
break;
@@ -1000,7 +1003,8 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
int staticPluginsFound = 0;
#if defined(QT_SHARED)
- foreach (const QQmlDirParser::Plugin &plugin, qmldir->plugins()) {
+ const auto qmldirPlugins = qmldir->plugins();
+ for (const QQmlDirParser::Plugin &plugin : qmldirPlugins) {
QString resolvedFilePath = database->resolvePlugin(typeLoader, qmldirPath, plugin.path, plugin.name);
if (!resolvedFilePath.isEmpty()) {
dynamicPluginsFound++;
@@ -1034,8 +1038,8 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
const QString basePath = QFileInfo(qmldirPath).absoluteFilePath();
for (const QString &versionUri : versionUris) {
- foreach (const StaticPluginPair &pair, pluginPairs) {
- foreach (const QJsonValue &metaTagUri, pair.second) {
+ for (const StaticPluginPair &pair : qAsConst(pluginPairs)) {
+ for (const QJsonValue &metaTagUri : pair.second) {
if (versionUri == metaTagUri.toString()) {
staticPluginsFound++;
QObject *instance = pair.first.instance();
@@ -1132,7 +1136,7 @@ QString QQmlImportsPrivate::resolvedUri(const QString &dir_arg, QQmlImportDataba
std::sort(paths.begin(), paths.end(), I::greaterThan); // Ensure subdirs preceed their parents.
QString stableRelativePath = dir;
- foreach(const QString &path, paths) {
+ for (const QString &path : qAsConst(paths)) {
if (dir.startsWith(path)) {
stableRelativePath = dir.mid(path.length()+1);
break;
@@ -1395,15 +1399,9 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix
// The uri for this import. For library imports this is the same as uri
// specified by the user, but it may be different in the case of file imports.
QString importUri = uri;
-
- QString qmldirPath = importUri;
- if (importUri.endsWith(Slash))
- qmldirPath += String_qmldir;
- else
- qmldirPath += Slash_qmldir;
-
- QString qmldirUrl = resolveLocalUrl(base, qmldirPath);
-
+ QString qmldirUrl = resolveLocalUrl(base, importUri + (importUri.endsWith(Slash)
+ ? String_qmldir
+ : Slash_qmldir));
QString qmldirIdentifier;
if (QQmlFile::isLocalFile(qmldirUrl)) {
@@ -1679,8 +1677,7 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader,
if (!qmldirPluginPathIsRelative)
searchPaths.prepend(qmldirPluginPath);
- foreach (const QString &pluginPath, searchPaths) {
-
+ for (const QString &pluginPath : qAsConst(searchPaths)) {
QString resolvedPath;
if (pluginPath == QLatin1String(".")) {
if (qmldirPluginPathIsRelative && !qmldirPluginPath.isEmpty() && qmldirPluginPath != QLatin1String("."))
@@ -1701,10 +1698,9 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader,
if (!resolvedPath.endsWith(Slash))
resolvedPath += Slash;
- foreach (const QString &suffix, suffixes) {
- QString pluginFileName = prefix + baseName + suffix;
-
- QString absolutePath = typeLoader->absoluteFilePath(resolvedPath + pluginFileName);
+ resolvedPath += prefix + baseName;
+ for (const QString &suffix : suffixes) {
+ const QString absolutePath = typeLoader->absoluteFilePath(resolvedPath + suffix);
if (!absolutePath.isEmpty())
return absolutePath;
}
@@ -1726,7 +1722,7 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader,
\header \li Platform \li Valid suffixes
\row \li Windows \li \c .dll
\row \li Unix/Linux \li \c .so
- \row \li OS X \li \c .dylib, \c .bundle, \c .so
+ \row \li \macos \li \c .dylib, \c .bundle, \c .so
\endtable
Version number on unix are ignored.
@@ -1736,29 +1732,32 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader,
const QString &baseName)
{
#if defined(Q_OS_WIN)
- return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName,
- QStringList()
+ static const QString prefix;
+ static const QStringList suffixes = {
# ifdef QT_DEBUG
- << QLatin1String("d.dll") // try a qmake-style debug build first
+ QLatin1String("d.dll"), // try a qmake-style debug build first
# endif
- << QLatin1String(".dll"));
+ QLatin1String(".dll")
+ };
#elif defined(Q_OS_DARWIN)
-
- return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName,
- QStringList()
+ static const QString prefix = QLatin1String("lib");
+ static const QStringList suffixes = {
# ifdef QT_DEBUG
- << QLatin1String("_debug.dylib") // try a qmake-style debug build first
- << QLatin1String(".dylib")
+ QLatin1String("_debug.dylib"), // try a qmake-style debug build first
+ QLatin1String(".dylib"),
# else
- << QLatin1String(".dylib")
- << QLatin1String("_debug.dylib") // try a qmake-style debug build after
+ QLatin1String(".dylib"),
+ QLatin1String("_debug.dylib"), // try a qmake-style debug build after
# endif
- << QLatin1String(".so")
- << QLatin1String(".bundle"),
- QLatin1String("lib"));
+ QLatin1String(".so"),
+ QLatin1String(".bundle")
+ };
# else // Unix
- return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, QStringList() << QLatin1String(".so"), QLatin1String("lib"));
+ static const QString prefix = QLatin1String("lib");
+ static const QStringList suffixes = { QLatin1String(".so") };
#endif
+
+ return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, suffixes, prefix);
}
/*!
@@ -1817,7 +1816,7 @@ void QQmlImportDatabase::addImportPath(const QString& path)
} else if (path.startsWith(QLatin1Char(':'))) {
// qrc directory, e.g. :/foo
// need to convert to a qrc url, e.g. qrc:/foo
- cPath = QStringLiteral("qrc") + path;
+ cPath = QLatin1String("qrc") + path;
cPath.replace(Backslash, Slash);
} else if (url.isRelative() ||
(url.scheme().length() == 1 && QFile::exists(path)) ) { // windows path
@@ -1842,7 +1841,7 @@ QStringList QQmlImportDatabase::importPathList(PathType type) const
return fileImportPath;
QStringList list;
- foreach (const QString &path, fileImportPath) {
+ for (const QString &path : fileImportPath) {
bool localPath = isPathAbsolute(path) || QQmlFile::isLocalFile(path);
if (localPath == (type == Local))
list.append(path);
@@ -1936,7 +1935,7 @@ bool QQmlImportDatabase::registerPluginTypes(QObject *instance, const QString &b
if (!registrationFailures.isEmpty()) {
if (errors) {
- foreach (const QString &failure, registrationFailures) {
+ for (const QString &failure : qAsConst(registrationFailures)) {
QQmlError error;
error.setDescription(failure);
errors->prepend(error);
@@ -1957,7 +1956,7 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba
#ifndef QT_NO_LIBRARY
// Dynamic plugins are differentiated by their filepath. For static plugins we
// don't have that information so we use their address as key instead.
- QString uniquePluginID = QString().sprintf("%p", instance);
+ const QString uniquePluginID = QString::asprintf("%p", instance);
StringRegisteredPluginMap *plugins = qmlEnginePluginsWithRegisteredTypes();
QMutexLocker lock(&plugins->mutex);
diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp
index eba93bfb1a..963638ca34 100644
--- a/src/qml/qml/qqmlincubator.cpp
+++ b/src/qml/qml/qqmlincubator.cpp
@@ -41,7 +41,6 @@
#include "qqmlcomponent.h"
#include "qqmlincubator_p.h"
-#include "qqmlcompiler_p.h"
#include "qqmlexpression_p.h"
#include "qqmlmemoryprofiler_p.h"
#include "qqmlobjectcreator_p.h"
@@ -132,7 +131,7 @@ QQmlIncubationController *QQmlEngine::incubationController() const
QQmlIncubatorPrivate::QQmlIncubatorPrivate(QQmlIncubator *q, QQmlIncubator::IncubationMode m)
: q(q), status(QQmlIncubator::Null), mode(m), isAsynchronous(false), progress(Execute),
- result(0), compiledData(0), waitingOnMe(0)
+ result(0), enginePriv(0), waitingOnMe(0)
{
}
@@ -143,20 +142,15 @@ QQmlIncubatorPrivate::~QQmlIncubatorPrivate()
void QQmlIncubatorPrivate::clear()
{
+ compilationUnit = nullptr;
if (next.isInList()) {
next.remove();
- Q_ASSERT(compiledData);
- QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(compiledData->engine);
- compiledData->release();
- compiledData = 0;
enginePriv->incubatorCount--;
QQmlIncubationController *controller = enginePriv->incubationController;
if (controller)
controller->incubatingObjectCountChanged(enginePriv->incubatorCount);
- } else if (compiledData) {
- compiledData->release();
- compiledData = 0;
}
+ enginePriv = 0;
if (!rootContext.isNull()) {
rootContext->activeVMEData = 0;
rootContext = 0;
@@ -212,7 +206,7 @@ public:
}
protected:
- virtual void timerEvent(QTimerEvent *) {
+ void timerEvent(QTimerEvent *) override {
incubateFor(5);
}
};
@@ -278,21 +272,20 @@ void QQmlIncubatorPrivate::forceCompletion(QQmlInstantiationInterrupt &i)
void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
{
- if (!compiledData)
+ if (!compilationUnit)
return;
- QML_MEMORY_SCOPE_URL(compiledData->compilationUnit->url());
+ QML_MEMORY_SCOPE_URL(compilationUnit->url());
QExplicitlySharedDataPointer<QQmlIncubatorPrivate> protectThis(this);
QRecursionWatcher<QQmlIncubatorPrivate, &QQmlIncubatorPrivate::recursion> watcher(this);
-
- QQmlEngine *engine = compiledData->engine;
- QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine);
+ // get a copy of the engine pointer as it might get reset;
+ QQmlEnginePrivate *enginePriv = this->enginePriv;
if (!vmeGuard.isOK()) {
QQmlError error;
- error.setUrl(compiledData->compilationUnit->url());
+ error.setUrl(compilationUnit->url());
error.setDescription(QQmlComponent::tr("Object destroyed during incubation"));
errors << error;
progress = QQmlIncubatorPrivate::Completed;
@@ -440,7 +433,7 @@ example shows a simple use of QQmlIncubator.
QQmlIncubator incubator;
component->create(incubator);
-while (incubator.isReady()) {
+while (!incubator.isReady()) {
QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
}
@@ -563,17 +556,16 @@ void QQmlIncubator::clear()
if (s == Null)
return;
- QQmlEnginePrivate *enginePriv = 0;
+ QQmlEnginePrivate *enginePriv = d->enginePriv;
if (s == Loading) {
- Q_ASSERT(d->compiledData);
- enginePriv = QQmlEnginePrivate::get(d->compiledData->engine);
+ Q_ASSERT(d->compilationUnit);
if (d->result) d->result->deleteLater();
d->result = 0;
}
d->clear();
- Q_ASSERT(d->compiledData == 0);
+ Q_ASSERT(d->compilationUnit.isNull());
Q_ASSERT(d->waitingOnMe.data() == 0);
Q_ASSERT(d->waitingFor.isEmpty());
@@ -713,7 +705,7 @@ QQmlIncubator::Status QQmlIncubatorPrivate::calculateStatus() const
return QQmlIncubator::Error;
else if (result && progress == QQmlIncubatorPrivate::Completed && waitingFor.isEmpty())
return QQmlIncubator::Ready;
- else if (compiledData)
+ else if (compilationUnit)
return QQmlIncubator::Loading;
else
return QQmlIncubator::Null;
diff --git a/src/qml/qml/qqmlincubator_p.h b/src/qml/qml/qqmlincubator_p.h
index a12ff9c5e2..ecf3b6d2ca 100644
--- a/src/qml/qml/qqmlincubator_p.h
+++ b/src/qml/qml/qqmlincubator_p.h
@@ -59,7 +59,6 @@
QT_BEGIN_NAMESPACE
-class QQmlCompiledData;
class QQmlIncubator;
class QQmlIncubatorPrivate : public QQmlEnginePrivate::Incubator
{
@@ -85,7 +84,8 @@ public:
QPointer<QObject> result;
QQmlGuardedContextData rootContext;
- QQmlCompiledData *compiledData;
+ QQmlEnginePrivate *enginePriv;
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
QScopedPointer<QQmlObjectCreator> creator;
int subComponentToCreate;
QQmlVMEGuard vmeGuard;
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 8ba4b5eba1..8020bdb2be 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -106,7 +106,8 @@ QQmlJavaScriptExpression::~QQmlJavaScriptExpression()
m_nextExpression->m_prevExpression = m_prevExpression;
}
- clearGuards();
+ clearActiveGuards();
+ clearPermanentGuards();
if (m_scopeObject.isT2()) // notify DeleteWatcher of our deletion.
m_scopeObject.asT2()->_s = 0;
}
@@ -114,12 +115,17 @@ QQmlJavaScriptExpression::~QQmlJavaScriptExpression()
void QQmlJavaScriptExpression::setNotifyOnValueChanged(bool v)
{
activeGuards.setFlagValue(v);
- if (!v) clearGuards();
+ permanentGuards.setFlagValue(v);
+ if (!v) {
+ clearActiveGuards();
+ clearPermanentGuards();
+ m_permanentDependenciesRegistered = false;
+ }
}
void QQmlJavaScriptExpression::resetNotifyOnValueChanged()
{
- clearGuards();
+ setNotifyOnValueChanged(false);
}
void QQmlJavaScriptExpression::setContext(QQmlContextData *context)
@@ -147,16 +153,9 @@ void QQmlJavaScriptExpression::refresh()
{
}
-QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(bool *isUndefined)
-{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_context->engine);
- QV4::Scope scope(v4);
- QV4::ScopedCallData callData(scope);
- return evaluate(callData, isUndefined);
-}
-QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, bool *isUndefined)
+void QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, bool *isUndefined, QV4::Scope &scope)
{
Q_ASSERT(m_context && m_context->engine);
@@ -164,7 +163,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
if (!f || f->isUndefined()) {
if (isUndefined)
*isUndefined = true;
- return QV4::Encode::undefined();
+ return;
}
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_context->engine);
@@ -184,8 +183,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
capture.guards.copyAndClearPrepend(activeGuards);
QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine());
- QV4::Scope scope(v4);
- QV4::ScopedValue result(scope, QV4::Primitive::undefinedValue());
+ scope.result = QV4::Primitive::undefinedValue();
callData->thisObject = v4->globalObject;
if (scopeObject()) {
QV4::ScopedValue value(scope, QV4::QObjectWrapper::wrap(v4, scopeObject()));
@@ -193,7 +191,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
callData->thisObject = value;
}
- result = f->as<QV4::FunctionObject>()->call(callData);
+ f->as<QV4::FunctionObject>()->call(scope, callData);
if (scope.hasException()) {
if (watcher.wasDeleted())
scope.engine->catchException(); // ignore exception
@@ -203,7 +201,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
*isUndefined = true;
} else {
if (isUndefined)
- *isUndefined = result->isUndefined();
+ *isUndefined = scope.result.isUndefined();
if (!watcher.wasDeleted() && hasDelayedError())
delayedError()->clearError();
@@ -220,11 +218,9 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
g->Delete();
ep->propertyCapture = lastPropertyCapture;
-
- return result->asReturnedValue();
}
-void QQmlPropertyCapture::captureProperty(QQmlNotifier *n)
+void QQmlPropertyCapture::captureProperty(QQmlNotifier *n, Duration duration)
{
if (watcher->wasDeleted())
return;
@@ -244,14 +240,17 @@ void QQmlPropertyCapture::captureProperty(QQmlNotifier *n)
g->connect(n);
}
- expression->activeGuards.prepend(g);
+ if (duration == Permanently)
+ expression->permanentGuards.prepend(g);
+ else
+ expression->activeGuards.prepend(g);
}
/*! \internal
\a n is in the signal index range (see QObjectPrivate::signalIndex()).
*/
-void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n)
+void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n, Duration duration)
{
if (watcher->wasDeleted())
return;
@@ -290,49 +289,60 @@ void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n)
g->connect(o, n, engine);
}
- expression->activeGuards.prepend(g);
+ if (duration == Permanently)
+ expression->permanentGuards.prepend(g);
+ else
+ expression->activeGuards.prepend(g);
}
}
-void QQmlPropertyCapture::registerQmlDependencies(QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction)
+void QQmlPropertyCapture::registerQmlDependencies(const QV4::CompiledData::Function *compiledFunction, const QV4::Scope &scope)
{
// Let the caller check and avoid the function call :)
Q_ASSERT(compiledFunction->hasQmlDependencies());
+ QV4::ExecutionEngine *engine = scope.engine;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine->qmlEngine());
if (!ep)
return;
QQmlPropertyCapture *capture = ep->propertyCapture;
- if (!capture)
+ if (!capture || capture->watcher->wasDeleted())
+ return;
+
+ if (capture->expression->m_permanentDependenciesRegistered)
return;
- QV4::Scope scope(engine);
+ capture->expression->m_permanentDependenciesRegistered = true;
+
QV4::Scoped<QV4::QmlContext> context(scope, engine->qmlContext());
QQmlContextData *qmlContext = context->qmlContext();
- const quint32 *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
+ const QV4::CompiledData::LEUInt32 *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
const int idObjectDependencyCount = compiledFunction->nDependingIdObjects;
for (int i = 0; i < idObjectDependencyCount; ++i, ++idObjectDependency) {
Q_ASSERT(int(*idObjectDependency) < qmlContext->idValueCount);
- capture->captureProperty(&qmlContext->idValues[*idObjectDependency].bindings);
+ capture->captureProperty(&qmlContext->idValues[*idObjectDependency].bindings,
+ QQmlPropertyCapture::Permanently);
}
Q_ASSERT(qmlContext->contextObject);
- const quint32 *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable();
+ const QV4::CompiledData::LEUInt32 *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable();
const int contextPropertyDependencyCount = compiledFunction->nDependingContextProperties;
for (int i = 0; i < contextPropertyDependencyCount; ++i) {
const int propertyIndex = *contextPropertyDependency++;
const int notifyIndex = *contextPropertyDependency++;
- capture->captureProperty(qmlContext->contextObject, propertyIndex, notifyIndex);
+ capture->captureProperty(qmlContext->contextObject, propertyIndex, notifyIndex,
+ QQmlPropertyCapture::Permanently);
}
QObject *scopeObject = context->qmlScope();
- const quint32 *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable();
+ const QV4::CompiledData::LEUInt32 *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable();
const int scopePropertyDependencyCount = compiledFunction->nDependingScopeProperties;
for (int i = 0; i < scopePropertyDependencyCount; ++i) {
const int propertyIndex = *scopePropertyDependency++;
const int notifyIndex = *scopePropertyDependency++;
- capture->captureProperty(scopeObject, propertyIndex, notifyIndex);
+ capture->captureProperty(scopeObject, propertyIndex, notifyIndex,
+ QQmlPropertyCapture::Permanently);
}
}
@@ -416,12 +426,19 @@ void QQmlJavaScriptExpression::createQmlBinding(QQmlContextData *ctxt, QObject *
}
-void QQmlJavaScriptExpression::clearGuards()
+void QQmlJavaScriptExpression::clearActiveGuards()
{
while (QQmlJavaScriptExpressionGuard *g = activeGuards.takeFirst())
g->Delete();
}
+void QQmlJavaScriptExpression::clearPermanentGuards()
+{
+ m_permanentDependenciesRegistered = false;
+ while (QQmlJavaScriptExpressionGuard *g = permanentGuards.takeFirst())
+ g->Delete();
+}
+
void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *e, void **)
{
QQmlJavaScriptExpression *expression =
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index 94479f6c5e..5f9cffb56d 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -103,8 +103,7 @@ public:
virtual QString expressionIdentifier() = 0;
virtual void expressionChanged() = 0;
- QV4::ReturnedValue evaluate(bool *isUndefined);
- QV4::ReturnedValue evaluate(QV4::CallData *callData, bool *isUndefined);
+ void evaluate(QV4::CallData *callData, bool *isUndefined, QV4::Scope &scope);
inline bool notifyOnValueChanged() const;
@@ -137,7 +136,8 @@ public:
inline bool hasDelayedError() const;
QQmlError error(QQmlEngine *) const;
void clearError();
- void clearGuards();
+ void clearActiveGuards();
+ void clearPermanentGuards();
QQmlDelayedError *delayedError();
static QV4::ReturnedValue evalFunction(QQmlContextData *ctxt, QObject *scope,
@@ -146,6 +146,14 @@ public:
protected:
void createQmlBinding(QQmlContextData *ctxt, QObject *scope, const QString &code, const QString &filename, quint16 line);
+ void cancelPermanentGuards() const
+ {
+ if (m_permanentDependenciesRegistered) {
+ for (QQmlJavaScriptExpressionGuard *it = permanentGuards.first(); it; it = permanentGuards.next(it))
+ it->cancelNotify();
+ }
+ }
+
private:
friend class QQmlContextData;
friend class QQmlPropertyCapture;
@@ -158,10 +166,12 @@ private:
// activeGuards:flag2 - useSharedContext
QBiPointer<QObject, DeleteWatcher> m_scopeObject;
QForwardFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> activeGuards;
+ QForwardFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> permanentGuards;
QQmlContextData *m_context;
QQmlJavaScriptExpression **m_prevExpression;
QQmlJavaScriptExpression *m_nextExpression;
+ bool m_permanentDependenciesRegistered = false;
protected:
QV4::PersistentValue m_function;
@@ -178,10 +188,14 @@ public:
Q_ASSERT(errorString == 0);
}
- void captureProperty(QQmlNotifier *);
- void captureProperty(QObject *, int, int);
+ enum Duration {
+ OnlyOnce,
+ Permanently
+ };
- static void registerQmlDependencies(QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction);
+ static void registerQmlDependencies(const QV4::CompiledData::Function *compiledFunction, const QV4::Scope &scope);
+ void captureProperty(QQmlNotifier *, Duration duration = OnlyOnce);
+ void captureProperty(QObject *, int, int, Duration duration = OnlyOnce);
QQmlEngine *engine;
QQmlJavaScriptExpression *expression;
diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp
index d0b7fb4853..a719956483 100644
--- a/src/qml/qml/qqmllist.cpp
+++ b/src/qml/qml/qqmllist.cpp
@@ -143,16 +143,16 @@ QQmlListReference::QQmlListReference(QObject *object, const char *property, QQml
QQmlEnginePrivate *p = engine?QQmlEnginePrivate::get(engine):0;
- int listType = p?p->listType(data->propType):QQmlMetaType::listType(data->propType);
+ int listType = p?p->listType(data->propType()):QQmlMetaType::listType(data->propType());
if (listType == -1) return;
d = new QQmlListReferencePrivate;
d->object = object;
d->elementType = p?p->rawMetaObjectForType(listType):QQmlMetaType::qmlType(listType)->baseMetaObject();
- d->propertyType = data->propType;
+ d->propertyType = data->propType();
void *args[] = { &d->property, 0 };
- QMetaObject::metacall(object, QMetaObject::ReadProperty, data->coreIndex, args);
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, data->coreIndex(), args);
}
/*! \internal */
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index 5c35866274..425a720867 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -54,6 +54,7 @@ DEFINE_OBJECT_VTABLE(QmlListWrapper);
Heap::QmlListWrapper::QmlListWrapper()
{
+ object.init();
QV4::Scope scope(internalClass->engine);
QV4::ScopedObject o(scope, this);
o->setArrayType(Heap::ArrayData::Custom);
@@ -61,6 +62,7 @@ Heap::QmlListWrapper::QmlListWrapper()
Heap::QmlListWrapper::~QmlListWrapper()
{
+ object.destroy();
}
ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, int propId, int propType)
diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h
index 26e1e5faaf..1107b957c9 100644
--- a/src/qml/qml/qqmllistwrapper_p.h
+++ b/src/qml/qml/qqmllistwrapper_p.h
@@ -68,7 +68,7 @@ namespace Heap {
struct QmlListWrapper : Object {
QmlListWrapper();
~QmlListWrapper();
- QPointer<QObject> object;
+ QQmlQPointer<QObject> object;
QQmlListProperty<QObject> property;
int propertyType;
};
diff --git a/src/qml/qml/qqmlloggingcategory.cpp b/src/qml/qml/qqmlloggingcategory.cpp
new file mode 100644
index 0000000000..88cf14cba0
--- /dev/null
+++ b/src/qml/qml/qqmlloggingcategory.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Pelagicore AG
+** 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 "qqmlloggingcategory_p.h"
+
+#include <QtQml/qqmlinfo.h>
+
+/*!
+ \qmltype LoggingCategory
+ \ingroup qml-utility-elements
+ \inqmlmodule QtQml
+ \brief Defines a logging category in QML
+ \since 5.8
+
+ A logging category can be passed to console.log() and friends as the first argument.
+ If supplied to to the logger the LoggingCategory's name will be used as Logging Category
+ otherwise the default logging category will be used.
+
+ \qml
+ import QtQuick 2.8
+
+ Item {
+ LoggingCategory {
+ id: category
+ name: "com.qt.category"
+ }
+
+ Component.onCompleted: {
+ console.log(category, "message");
+ }
+ }
+ \endqml
+
+ \note As the creation of objects is expensive, it is encouraged to put the needed
+ LoggingCategory definitions into a singleton and import this where needed.
+
+ \sa QLoggingCategory
+*/
+
+/*!
+ \qmlproperty string QtQml::LoggingCategory::name
+
+ Holds the name of the logging category.
+
+ \note This property needs to be set when declaring the LoggingCategory
+ and cannot be changed later.
+
+ \sa QLoggingCategory::name()
+*/
+
+QQmlLoggingCategory::QQmlLoggingCategory(QObject *parent)
+ : QObject(parent)
+ , m_initialized(false)
+{
+}
+
+QQmlLoggingCategory::~QQmlLoggingCategory()
+{
+}
+
+QString QQmlLoggingCategory::name() const
+{
+ return QString::fromUtf8(m_name);
+}
+
+QLoggingCategory *QQmlLoggingCategory::category() const
+{
+ return m_category.data();
+}
+
+void QQmlLoggingCategory::classBegin()
+{
+}
+
+void QQmlLoggingCategory::componentComplete()
+{
+ m_initialized = true;
+ if (m_name.isNull())
+ qmlInfo(this) << QString(QLatin1String("Declaring the name of the LoggingCategory is mandatory and cannot be changed later !"));
+}
+
+void QQmlLoggingCategory::setName(const QString &name)
+{
+ if (m_initialized) {
+ qmlInfo(this) << QString(QLatin1String("The name of a LoggingCategory cannot be changed after the Item is created"));
+ return;
+ }
+
+ m_name = name.toUtf8();
+ QScopedPointer<QLoggingCategory> category(new QLoggingCategory(m_name.constData()));
+ m_category.swap(category);
+}
diff --git a/src/qml/qml/ftw/qdeletewatcher_p.h b/src/qml/qml/qqmlloggingcategory_p.h
index d4c0c6dfb2..2b7f2f5b53 100644
--- a/src/qml/qml/ftw/qdeletewatcher_p.h
+++ b/src/qml/qml/qqmlloggingcategory_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Pelagicore AG
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QDELETEWATCHER_P_H
-#define QDELETEWATCHER_P_H
+#ifndef QQMLLOGGINGCATEGORY_P_H
+#define QQMLLOGGINGCATEGORY_P_H
//
// W A R N I N G
@@ -51,61 +51,39 @@
// We mean it.
//
-#include <QtCore/qglobal.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qloggingcategory.h>
+
+#include <QtQml/qqmlparserstatus.h>
QT_BEGIN_NAMESPACE
-class QDeleteWatchable
+class QQmlLoggingCategory : public QObject, public QQmlParserStatus
{
-public:
- inline QDeleteWatchable();
- inline ~QDeleteWatchable();
-private:
- friend class QDeleteWatcher;
- bool *_w;
-};
+ Q_OBJECT
+ Q_INTERFACES(QQmlParserStatus)
-class QDeleteWatcher {
-public:
- inline QDeleteWatcher(QDeleteWatchable *data);
- inline ~QDeleteWatcher();
- inline bool wasDeleted() const;
-private:
- void *operator new(size_t);
- bool *_w;
- bool _s;
- QDeleteWatchable *m_d;
-};
+ Q_PROPERTY(QString name READ name WRITE setName)
-QDeleteWatchable::QDeleteWatchable()
-: _w(0)
-{
-}
+public:
+ QQmlLoggingCategory(QObject *parent = 0);
+ virtual ~QQmlLoggingCategory();
-QDeleteWatchable::~QDeleteWatchable()
-{
- if (_w) *_w = true;
-}
+ QString name() const;
+ void setName(const QString &name);
-QDeleteWatcher::QDeleteWatcher(QDeleteWatchable *data)
-: _s(false), m_d(data)
-{
- if (!m_d->_w)
- m_d->_w = &_s;
- _w = m_d->_w;
-}
+ QLoggingCategory *category() const;
-QDeleteWatcher::~QDeleteWatcher()
-{
- if (false == *_w && &_s == m_d->_w)
- m_d->_w = 0;
-}
+ void classBegin() override;
+ void componentComplete() override;
-bool QDeleteWatcher::wasDeleted() const
-{
- return *_w;
-}
+private:
+ QByteArray m_name;
+ QScopedPointer<QLoggingCategory> m_category;
+ bool m_initialized;
+};
QT_END_NAMESPACE
-#endif // QDELETEWATCHER_P_H
+#endif // QQMLLOGGINGCATEGORY_H
diff --git a/src/qml/qml/qqmlmemoryprofiler.cpp b/src/qml/qml/qqmlmemoryprofiler.cpp
deleted file mode 100644
index 60f6d96eaf..0000000000
--- a/src/qml/qml/qqmlmemoryprofiler.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlmemoryprofiler_p.h"
-#include <QUrl>
-
-QT_BEGIN_NAMESPACE
-
-enum LibraryState
-{
- Unloaded,
- Failed,
- Loaded
-};
-
-static LibraryState state = Unloaded;
-
-typedef void (qmlmemprofile_stats)(int *allocCount, int *bytesAllocated);
-typedef void (qmlmemprofile_clear)();
-typedef void (qmlmemprofile_enable)();
-typedef void (qmlmemprofile_disable)();
-typedef void (qmlmemprofile_push_location)(const char *filename, int lineNumber);
-typedef void (qmlmemprofile_pop_location)();
-typedef void (qmlmemprofile_save)(const char *filename);
-typedef int (qmlmemprofile_is_enabled)();
-
-static qmlmemprofile_stats *memprofile_stats;
-static qmlmemprofile_clear *memprofile_clear;
-static qmlmemprofile_enable *memprofile_enable;
-static qmlmemprofile_disable *memprofile_disable;
-static qmlmemprofile_push_location *memprofile_push_location;
-static qmlmemprofile_pop_location *memprofile_pop_location;
-static qmlmemprofile_save *memprofile_save;
-static qmlmemprofile_is_enabled *memprofile_is_enabled;
-
-#ifndef QT_NO_LIBRARY
-extern QFunctionPointer qt_linux_find_symbol_sys(const char *symbol);
-#endif
-
-static bool openLibrary()
-{
-#if defined(Q_OS_LINUX) && !defined(QT_NO_LIBRARY)
- if (state == Unloaded) {
- memprofile_stats = (qmlmemprofile_stats *) qt_linux_find_symbol_sys("qmlmemprofile_stats");
- memprofile_clear = (qmlmemprofile_clear *) qt_linux_find_symbol_sys("qmlmemprofile_clear");
- memprofile_enable = (qmlmemprofile_enable *) qt_linux_find_symbol_sys("qmlmemprofile_enable");
- memprofile_disable = (qmlmemprofile_disable *) qt_linux_find_symbol_sys("qmlmemprofile_disable");
- memprofile_push_location = (qmlmemprofile_push_location *) qt_linux_find_symbol_sys("qmlmemprofile_push_location");
- memprofile_pop_location = (qmlmemprofile_pop_location *) qt_linux_find_symbol_sys("qmlmemprofile_pop_location");
- memprofile_save = (qmlmemprofile_save *) qt_linux_find_symbol_sys("qmlmemprofile_save");
- memprofile_is_enabled = (qmlmemprofile_is_enabled *) qt_linux_find_symbol_sys("qmlmemprofile_is_enabled");
-
- if (memprofile_stats && memprofile_clear && memprofile_enable && memprofile_disable &&
- memprofile_push_location && memprofile_pop_location && memprofile_save && memprofile_is_enabled)
- state = Loaded;
- else
- state = Failed;
- }
-#endif // Q_OS_LINUX
-
- return state == Loaded;
-}
-
-QQmlMemoryScope::QQmlMemoryScope(const QUrl &url)
- : QQmlMemoryScope(url.path().toUtf8().constData())
-{
-}
-
-QQmlMemoryScope::QQmlMemoryScope(const char *string) : pushed(false)
-{
- if (openLibrary() && memprofile_is_enabled()) {
- memprofile_push_location(string, 0);
- pushed = true;
- }
-}
-
-QQmlMemoryScope::~QQmlMemoryScope()
-{
- if (pushed)
- memprofile_pop_location();
-}
-
-bool QQmlMemoryProfiler::isEnabled()
-{
- if (openLibrary())
- return memprofile_is_enabled();
-
- return false;
-}
-
-void QQmlMemoryProfiler::enable()
-{
- if (openLibrary())
- memprofile_enable();
-}
-
-void QQmlMemoryProfiler::disable()
-{
- if (openLibrary())
- memprofile_disable();
-}
-
-void QQmlMemoryProfiler::clear()
-{
- if (openLibrary())
- memprofile_clear();
-}
-
-void QQmlMemoryProfiler::stats(int *allocCount, int *bytesAllocated)
-{
- if (openLibrary())
- memprofile_stats(allocCount, bytesAllocated);
-}
-
-void QQmlMemoryProfiler::save(const char *filename)
-{
- if (openLibrary())
- memprofile_save(filename);
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 1b3997baae..08acb330b1 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -44,7 +44,6 @@
#include <private/qqmlcustomparser_p.h>
#include <private/qhashedstring_p.h>
#include <private/qqmlimport_p.h>
-#include <private/qqmlcompiler_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qstringlist.h>
@@ -490,11 +489,11 @@ QQmlType *QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
Q_ASSERT(isComposite());
if (!engine)
return 0;
- QQmlTypeData *td = engine->typeLoader.getType(sourceUrl());
- if (!td || !td->isComplete())
+ QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()), QQmlRefPointer<QQmlTypeData>::Adopt);
+ if (td.isNull() || !td->isComplete())
return 0;
- QQmlCompiledData *cd = td->compiledData();
- const QMetaObject *mo = cd->compilationUnit->rootPropertyCache()->firstCppMetaObject();
+ QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
+ const QMetaObject *mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
return QQmlMetaType::qmlType(mo);
}
@@ -635,7 +634,7 @@ void QQmlTypePrivate::init() const
QMetaObject *mmo = builder.toMetaObject();
mmo->d.superdata = baseMetaObject;
if (!metaObjects.isEmpty())
- metaObjects.last().metaObject->d.superdata = mmo;
+ metaObjects.constLast().metaObject->d.superdata = mmo;
QQmlProxyMetaObject::ProxyData data = { mmo, t->d->extraData.cd->extFunc, 0, 0 };
metaObjects << data;
}
@@ -657,7 +656,7 @@ void QQmlTypePrivate::init() const
if (metaObjects.isEmpty())
mo = baseMetaObject;
else
- mo = metaObjects.first().metaObject;
+ mo = metaObjects.constFirst().metaObject;
for (int ii = 0; !containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) {
if (isPropertyRevisioned(mo, ii))
@@ -852,7 +851,7 @@ const QMetaObject *QQmlType::metaObject() const
if (d->metaObjects.isEmpty())
return d->baseMetaObject;
else
- return d->metaObjects.first().metaObject;
+ return d->metaObjects.constFirst().metaObject;
}
@@ -1445,11 +1444,11 @@ bool qmlProtectModule(const char *uri, int majVersion)
bool QQmlMetaType::namespaceContainsRegistrations(const QString &uri, int majorVersion)
{
- QQmlMetaTypeData *data = metaTypeData();
+ const QQmlMetaTypeData *data = metaTypeData();
// Has any type previously been installed to this namespace?
QHashedString nameSpace(uri);
- foreach (const QQmlType *type, data->types)
+ for (const QQmlType *type : data->types)
if (type->module() == nameSpace && type->majorVersion() == majorVersion)
return true;
@@ -1862,7 +1861,7 @@ QQmlType *QQmlMetaType::qmlTypeFromIndex(int idx)
if (idx < 0 || idx >= data->types.count())
return 0;
- return data->types[idx];
+ return data->types.at(idx);
}
/*!
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index dcd35bccad..2218f277d6 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -69,41 +69,43 @@ struct ActiveOCRestorer
};
}
-QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlContextData *creationContext, void *activeVMEDataForRootContext)
+QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QV4::CompiledData::CompilationUnit *compilationUnit, QQmlContextData *creationContext, void *activeVMEDataForRootContext)
: phase(Startup)
- , compiledData(compiledData)
- , resolvedTypes(compiledData->resolvedTypes)
- , propertyCaches(compiledData->compilationUnit->propertyCaches)
+ , compilationUnit(compilationUnit)
+ , resolvedTypes(compilationUnit->resolvedTypes)
+ , propertyCaches(&compilationUnit->propertyCaches)
+ , sharedState(new QQmlObjectCreatorSharedState)
+ , topLevelCreator(true)
, activeVMEDataForRootContext(activeVMEDataForRootContext)
{
init(parentContext);
- sharedState = new QQmlObjectCreatorSharedState;
- topLevelCreator = true;
sharedState->componentAttached = 0;
- sharedState->allCreatedBindings.allocate(compiledData->compilationUnit->totalBindingsCount);
- sharedState->allParserStatusCallbacks.allocate(compiledData->compilationUnit->totalParserStatusCount);
- sharedState->allCreatedObjects.allocate(compiledData->compilationUnit->totalObjectCount);
+ sharedState->allCreatedBindings.allocate(compilationUnit->totalBindingsCount);
+ sharedState->allParserStatusCallbacks.allocate(compilationUnit->totalParserStatusCount);
+ sharedState->allCreatedObjects.allocate(compilationUnit->totalObjectCount);
sharedState->allJavaScriptObjects = 0;
sharedState->creationContext = creationContext;
sharedState->rootContext = 0;
- QQmlProfiler *profiler = QQmlEnginePrivate::get(engine)->profiler;
- Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler,
- sharedState->profiler.init(profiler, compiledData->compilationUnit->totalParserStatusCount));
+ if (auto profiler = QQmlEnginePrivate::get(engine)->profiler) {
+ Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler,
+ sharedState->profiler.init(profiler, compilationUnit->totalParserStatusCount));
+ } else {
+ Q_UNUSED(profiler);
+ }
}
-QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlObjectCreatorSharedState *inheritedSharedState)
+QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QV4::CompiledData::CompilationUnit *compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState)
: phase(Startup)
- , compiledData(compiledData)
- , resolvedTypes(compiledData->resolvedTypes)
- , propertyCaches(compiledData->compilationUnit->propertyCaches)
+ , compilationUnit(compilationUnit)
+ , resolvedTypes(compilationUnit->resolvedTypes)
+ , propertyCaches(&compilationUnit->propertyCaches)
+ , sharedState(inheritedSharedState)
+ , topLevelCreator(false)
, activeVMEDataForRootContext(0)
{
init(parentContext);
-
- sharedState = inheritedSharedState;
- topLevelCreator = false;
}
void QQmlObjectCreator::init(QQmlContextData *providedParentContext)
@@ -112,13 +114,14 @@ void QQmlObjectCreator::init(QQmlContextData *providedParentContext)
engine = parentContext->engine;
v4 = QV8Engine::getV4(engine);
- if (!compiledData->isInitialized())
- compiledData->initialize(engine);
+ if (compilationUnit && !compilationUnit->engine)
+ compilationUnit->linkToEngine(v4);
- qmlUnit = compiledData->compilationUnit->data;
+ qmlUnit = compilationUnit->data;
context = 0;
_qobject = 0;
_scopeObject = 0;
+ _bindingTarget = 0;
_valueTypeProperty = 0;
_compiledObject = 0;
_compiledObjectIndex = -1;
@@ -166,9 +169,8 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
context = new QQmlContextData;
context->isInternal = true;
- context->imports = compiledData->compilationUnit->importCache;
- context->imports->addref();
- context->initFromTypeCompilationUnit(compiledData->compilationUnit, subComponentIndex);
+ context->imports = compilationUnit->importCache;
+ context->initFromTypeCompilationUnit(compilationUnit, subComponentIndex);
context->setParent(parentContext);
if (!sharedState->rootContext) {
@@ -181,14 +183,14 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
Q_ASSERT(sharedState->allJavaScriptObjects || topLevelCreator);
if (topLevelCreator)
- sharedState->allJavaScriptObjects = scope.alloc(compiledData->compilationUnit->totalObjectCount);
+ sharedState->allJavaScriptObjects = scope.alloc(compilationUnit->totalObjectCount);
- if (subComponentIndex == -1 && compiledData->compilationUnit->dependentScripts.count()) {
- QV4::ScopedObject scripts(scope, v4->newArrayObject(compiledData->compilationUnit->dependentScripts.count()));
+ if (subComponentIndex == -1 && compilationUnit->dependentScripts.count()) {
+ QV4::ScopedObject scripts(scope, v4->newArrayObject(compilationUnit->dependentScripts.count()));
context->importedScripts.set(v4, scripts);
QV4::ScopedValue v(scope);
- for (int i = 0; i < compiledData->compilationUnit->dependentScripts.count(); ++i) {
- QQmlScriptData *s = compiledData->compilationUnit->dependentScripts.at(i);
+ for (int i = 0; i < compilationUnit->dependentScripts.count(); ++i) {
+ QQmlScriptData *s = compilationUnit->dependentScripts.at(i);
scripts->putIndexed(i, (v = s->scriptValueForContext(context)));
}
} else if (sharedState->creationContext) {
@@ -199,10 +201,10 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
if (instance) {
QQmlData *ddata = QQmlData::get(instance);
Q_ASSERT(ddata);
- if (ddata->compiledData)
- ddata->compiledData->release();
- ddata->compiledData = compiledData;
- ddata->compiledData->addref();
+ if (ddata->compilationUnit)
+ ddata->compilationUnit->release();
+ ddata->compilationUnit = compilationUnit;
+ ddata->compilationUnit->addref();
}
if (topLevelCreator)
@@ -236,7 +238,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
Q_ASSERT(topLevelCreator);
Q_ASSERT(!sharedState->allJavaScriptObjects);
- sharedState->allJavaScriptObjects = valueScope.alloc(compiledData->compilationUnit->totalObjectCount);
+ sharedState->allJavaScriptObjects = valueScope.alloc(compilationUnit->totalObjectCount);
QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc(1));
@@ -275,14 +277,10 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
{
- QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
- int propertyWriteStatus = -1;
- void *argv[] = { 0, 0, &propertyWriteStatus, &propertyWriteFlags };
-
+ QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor | QQmlPropertyData::RemoveBindingOnAliasWrite;
QV4::Scope scope(v4);
- int propertyType = property->propType;
+ int propertyType = property->propType();
if (property->isEnum()) {
if (binding->flags & QV4::CompiledData::Binding::IsResolvedEnum) {
@@ -303,39 +301,35 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
double n = binding->valueAsNumber();
if (double(int(n)) == n) {
if (property->isVarProperty()) {
- _vmeMetaObject->setVMEProperty(property->coreIndex, QV4::Primitive::fromInt32(int(n)));
+ _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Primitive::fromInt32(int(n)));
} else {
int i = int(n);
QVariant value(i);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
} else {
if (property->isVarProperty()) {
- _vmeMetaObject->setVMEProperty(property->coreIndex, QV4::Primitive::fromDouble(n));
+ _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Primitive::fromDouble(n));
} else {
QVariant value(n);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
}
} else if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
if (property->isVarProperty()) {
- _vmeMetaObject->setVMEProperty(property->coreIndex, QV4::Primitive::fromBoolean(binding->valueAsBoolean()));
+ _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Primitive::fromBoolean(binding->valueAsBoolean()));
} else {
QVariant value(binding->valueAsBoolean());
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
} else {
QString stringValue = binding->valueAsString(qmlUnit);
if (property->isVarProperty()) {
QV4::ScopedString s(scope, v4->newString(stringValue));
- _vmeMetaObject->setVMEProperty(property->coreIndex, s);
+ _vmeMetaObject->setVMEProperty(property->coreIndex(), s);
} else {
QVariant value = QQmlStringConverters::variantFromString(stringValue);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
}
}
@@ -343,22 +337,19 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
case QVariant::String: {
Q_ASSERT(binding->evaluatesToString());
QString value = binding->valueAsString(qmlUnit);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::StringList: {
Q_ASSERT(binding->evaluatesToString());
QStringList value(binding->valueAsString(qmlUnit));
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::ByteArray: {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
QByteArray value(binding->valueAsString(qmlUnit).toUtf8());
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Url: {
@@ -366,20 +357,18 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
QString string = binding->valueAsString(qmlUnit);
// Encoded dir-separators defeat QUrl processing - decode them first
string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
- QUrl value = string.isEmpty() ? QUrl() : compiledData->compilationUnit->url().resolved(QUrl(string));
+ QUrl value = string.isEmpty() ? QUrl() : compilationUnit->url().resolved(QUrl(string));
// Apply URL interceptor
if (engine->urlInterceptor())
value = engine->urlInterceptor()->intercept(value, QQmlAbstractUrlInterceptor::UrlString);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::UInt: {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
double d = binding->valueAsNumber();
uint value = uint(d);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
}
break;
@@ -387,23 +376,20 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
double d = binding->valueAsNumber();
int value = int(d);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
}
break;
case QMetaType::Float: {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
float value = float(binding->valueAsNumber());
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Double: {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
double value = binding->valueAsNumber();
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Color: {
@@ -411,9 +397,8 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
uint colorValue = QQmlStringConverters::rgbaFromString(binding->valueAsString(qmlUnit), &ok);
Q_ASSERT(ok);
struct { void *data[4]; } buffer;
- if (QQml_valueTypeProvider()->storeValueType(property->propType, &colorValue, &buffer, sizeof(buffer))) {
- argv[0] = reinterpret_cast<void *>(&buffer);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ if (QQml_valueTypeProvider()->storeValueType(property->propType(), &colorValue, &buffer, sizeof(buffer))) {
+ property->writeProperty(_qobject, &buffer, propertyWriteFlags);
}
}
break;
@@ -422,16 +407,14 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
bool ok = false;
QDate value = QQmlStringConverters::dateFromString(binding->valueAsString(qmlUnit), &ok);
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Time: {
bool ok = false;
QTime value = QQmlStringConverters::timeFromString(binding->valueAsString(qmlUnit), &ok);
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::DateTime: {
@@ -444,8 +427,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
value = QDateTime(QDate::fromJulianDay(date), QTime::fromMSecsSinceStartOfDay(msecsSinceStartOfDay));
}
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
#endif // QT_NO_DATESTRING
@@ -453,55 +435,59 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
bool ok = false;
QPoint value = QQmlStringConverters::pointFFromString(binding->valueAsString(qmlUnit), &ok).toPoint();
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::PointF: {
bool ok = false;
QPointF value = QQmlStringConverters::pointFFromString(binding->valueAsString(qmlUnit), &ok);
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Size: {
bool ok = false;
QSize value = QQmlStringConverters::sizeFFromString(binding->valueAsString(qmlUnit), &ok).toSize();
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::SizeF: {
bool ok = false;
QSizeF value = QQmlStringConverters::sizeFFromString(binding->valueAsString(qmlUnit), &ok);
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Rect: {
bool ok = false;
QRect value = QQmlStringConverters::rectFFromString(binding->valueAsString(qmlUnit), &ok).toRect();
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::RectF: {
bool ok = false;
QRectF value = QQmlStringConverters::rectFFromString(binding->valueAsString(qmlUnit), &ok);
Q_ASSERT(ok);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
case QVariant::Bool: {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Boolean);
bool value = binding->valueAsBoolean();
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
+ }
+ break;
+ case QVariant::Vector2D: {
+ struct {
+ float xp;
+ float yp;
+ } vec;
+ bool ok = QQmlStringConverters::createFromString(QMetaType::QVector2D, binding->valueAsString(qmlUnit), &vec, sizeof(vec));
+ Q_ASSERT(ok);
+ Q_UNUSED(ok);
+ property->writeProperty(_qobject, &vec, propertyWriteFlags);
}
break;
case QVariant::Vector3D: {
@@ -513,8 +499,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
bool ok = QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(qmlUnit), &vec, sizeof(vec));
Q_ASSERT(ok);
Q_UNUSED(ok);
- argv[0] = reinterpret_cast<void *>(&vec);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &vec, propertyWriteFlags);
}
break;
case QVariant::Vector4D: {
@@ -527,8 +512,20 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
bool ok = QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(qmlUnit), &vec, sizeof(vec));
Q_ASSERT(ok);
Q_UNUSED(ok);
- argv[0] = reinterpret_cast<void *>(&vec);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &vec, propertyWriteFlags);
+ }
+ break;
+ case QVariant::Quaternion: {
+ struct {
+ float wp;
+ float xp;
+ float yp;
+ float zp;
+ } vec;
+ bool ok = QQmlStringConverters::createFromString(QMetaType::QQuaternion, binding->valueAsString(qmlUnit), &vec, sizeof(vec));
+ Q_ASSERT(ok);
+ Q_UNUSED(ok);
+ property->writeProperty(_qobject, &vec, propertyWriteFlags);
}
break;
case QVariant::RegExp:
@@ -536,45 +533,40 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
break;
default: {
// generate single literal value assignment to a list property if required
- if (property->propType == qMetaTypeId<QList<qreal> >()) {
+ if (property->propType() == qMetaTypeId<QList<qreal> >()) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
QList<qreal> value;
value.append(binding->valueAsNumber());
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
- } else if (property->propType == qMetaTypeId<QList<int> >()) {
+ } else if (property->propType() == qMetaTypeId<QList<int> >()) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
double n = binding->valueAsNumber();
QList<int> value;
value.append(int(n));
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
- } else if (property->propType == qMetaTypeId<QList<bool> >()) {
+ } else if (property->propType() == qMetaTypeId<QList<bool> >()) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Boolean);
QList<bool> value;
value.append(binding->valueAsBoolean());
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
- } else if (property->propType == qMetaTypeId<QList<QUrl> >()) {
+ } else if (property->propType() == qMetaTypeId<QList<QUrl> >()) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
QString urlString = binding->valueAsString(qmlUnit);
- QUrl u = urlString.isEmpty() ? QUrl() : compiledData->compilationUnit->url().resolved(QUrl(urlString));
+ QUrl u = urlString.isEmpty() ? QUrl() : compilationUnit->url().resolved(QUrl(urlString));
QList<QUrl> value;
value.append(u);
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
- } else if (property->propType == qMetaTypeId<QList<QString> >()) {
+ } else if (property->propType() == qMetaTypeId<QList<QString> >()) {
Q_ASSERT(binding->evaluatesToString());
QList<QString> value;
value.append(binding->valueAsString(qmlUnit));
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
- } else if (property->propType == qMetaTypeId<QJSValue>()) {
+ } else if (property->propType() == qMetaTypeId<QJSValue>()) {
QJSValue value;
if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
value = QJSValue(binding->valueAsBoolean());
@@ -587,25 +579,23 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
} else {
value = QJSValue(binding->valueAsString(qmlUnit));
}
- argv[0] = reinterpret_cast<void *>(&value);
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
}
// otherwise, try a custom type assignment
QString stringValue = binding->valueAsString(qmlUnit);
- QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(property->propType);
+ QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(property->propType());
Q_ASSERT(converter);
QVariant value = (*converter)(stringValue);
- QMetaProperty metaProperty = _qobject->metaObject()->property(property->coreIndex);
- if (value.isNull() || ((int)metaProperty.type() != property->propType && metaProperty.userType() != property->propType)) {
+ QMetaProperty metaProperty = _qobject->metaObject()->property(property->coreIndex());
+ if (value.isNull() || ((int)metaProperty.type() != property->propType() && metaProperty.userType() != property->propType())) {
recordError(binding->location, tr("Cannot assign value %1 to property %2").arg(stringValue).arg(QString::fromUtf8(metaProperty.name())));
break;
}
- argv[0] = value.data();
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ property->writeProperty(_qobject, value.data(), propertyWriteFlags);
}
break;
}
@@ -627,12 +617,12 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
QQmlListProperty<void> savedList;
qSwap(_currentList, savedList);
- const QV4::CompiledData::BindingPropertyData &propertyData = compiledData->compilationUnit->bindingPropertyDataPerObject.at(_compiledObjectIndex);
+ const QV4::CompiledData::BindingPropertyData &propertyData = compilationUnit->bindingPropertyDataPerObject.at(_compiledObjectIndex);
if (_compiledObject->idNameIndex) {
const QQmlPropertyData *idProperty = propertyData.last();
Q_ASSERT(!idProperty || !idProperty->isValid() || idProperty->name(_qobject) == QLatin1String("id"));
- if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType == QMetaType::QString) {
+ if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType() == QMetaType::QString) {
QV4::CompiledData::Binding idBinding;
idBinding.propertyNameIndex = 0; // Not used
idBinding.flags = 0;
@@ -645,10 +635,10 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
// ### this is best done through type-compile-time binding skip lists.
if (_valueTypeProperty) {
- QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(_bindingTarget, _valueTypeProperty->coreIndex);
+ QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(_bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex()));
if (binding && !binding->isValueTypeProxy()) {
- QQmlPropertyPrivate::removeBinding(_bindingTarget, _valueTypeProperty->coreIndex);
+ QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex()));
} else if (binding) {
QQmlValueTypeProxyBinding *proxy = static_cast<QQmlValueTypeProxyBinding *>(binding);
@@ -661,7 +651,7 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
QQmlPropertyData *property = binding->propertyNameIndex != 0 ? _propertyCache->property(stringAt(binding->propertyNameIndex), _qobject, context) : defaultProperty;
if (property)
- bindingSkipList |= (1 << property->coreIndex);
+ bindingSkipList |= (1 << property->coreIndex());
}
proxy->removeBindings(bindingSkipList);
@@ -687,10 +677,10 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
const QQmlPropertyData *property = propertyData.at(i);
if (property && property->isQList()) {
- if (property->coreIndex != currentListPropertyIndex) {
+ if (property->coreIndex() != currentListPropertyIndex) {
void *argv[1] = { (void*)&_currentList };
- QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex, argv);
- currentListPropertyIndex = property->coreIndex;
+ QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex(), argv);
+ currentListPropertyIndex = property->coreIndex();
}
} else if (_currentList.object) {
_currentList = QQmlListProperty<void>();
@@ -708,7 +698,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
{
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
Q_ASSERT(stringAt(qmlUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty());
- QQmlCompiledData::TypeReference *tr = resolvedTypes.value(binding->propertyNameIndex);
+ QV4::CompiledData::ResolvedTypeReference *tr = resolvedTypes.value(binding->propertyNameIndex);
Q_ASSERT(tr);
QQmlType *attachedType = tr->type;
if (!attachedType) {
@@ -726,7 +716,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
}
// ### resolve this at compile time
- if (property && property->propType == qMetaTypeId<QQmlScriptString>()) {
+ if (property && property->propType() == qMetaTypeId<QQmlScriptString>()) {
QQmlScriptString ss(binding->valueAsScriptString(qmlUnit), context->asQQmlContext(), _scopeObject);
ss.d.data()->bindingId = binding->type == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : (quint32)QQmlBinding::Invalid;
ss.d.data()->lineNumber = binding->location.line;
@@ -735,11 +725,11 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
ss.d.data()->isNumberLiteral = binding->type == QV4::CompiledData::Binding::Type_Number;
ss.d.data()->numberValue = binding->valueAsNumber();
- QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
+ QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor |
+ QQmlPropertyData::RemoveBindingOnAliasWrite;
int propertyWriteStatus = -1;
void *argv[] = { &ss, 0, &propertyWriteStatus, &propertyWriteFlags };
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex(), argv);
return true;
}
@@ -762,20 +752,20 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
const QQmlPropertyData *valueTypeProperty = 0;
QObject *bindingTarget = _bindingTarget;
- if (QQmlValueTypeFactory::isValueType(property->propType)) {
- valueType = QQmlValueTypeFactory::valueType(property->propType);
+ if (QQmlValueTypeFactory::isValueType(property->propType())) {
+ valueType = QQmlValueTypeFactory::valueType(property->propType());
if (!valueType) {
recordError(binding->location, tr("Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex)));
return false;
}
- valueType->read(_qobject, property->coreIndex);
+ valueType->read(_qobject, property->coreIndex());
groupObject = valueType;
valueTypeProperty = property;
} else {
void *argv[1] = { &groupObject };
- QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex, argv);
+ QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex(), argv);
if (!groupObject) {
recordError(binding->location, tr("Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex)));
return false;
@@ -788,48 +778,49 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
return false;
if (valueType)
- valueType->write(_qobject, property->coreIndex, QQmlPropertyPrivate::BypassInterceptor);
+ valueType->write(_qobject, property->coreIndex(), QQmlPropertyData::BypassInterceptor);
return true;
}
}
- if (_ddata->hasBindingBit(property->coreIndex) && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
+ if (_ddata->hasBindingBit(property->coreIndex()) && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
&& !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment)
&& !_valueTypeProperty)
- QQmlPropertyPrivate::removeBinding(_bindingTarget, property->coreIndex);
+ QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(property->coreIndex()));
if (binding->type == QV4::CompiledData::Binding::Type_Script) {
- QV4::Function *runtimeFunction = compiledData->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
+ QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
QV4::Scope scope(v4);
QV4::ScopedContext qmlContext(scope, currentQmlContext());
QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::createScriptFunction(qmlContext, runtimeFunction, /*createProto*/ false));
if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) {
- int signalIndex = _propertyCache->methodIndexToSignalIndex(property->coreIndex);
+ int signalIndex = _propertyCache->methodIndexToSignalIndex(property->coreIndex());
QQmlBoundSignal *bs = new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine);
QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(_bindingTarget, signalIndex,
context, _scopeObject, function);
bs->takeExpression(expr);
} else {
- QQmlBinding *qmlBinding = new QQmlBinding(function, _scopeObject, context);
-
// When writing bindings to grouped properties implemented as value types,
// such as point.x: { someExpression; }, then the binding is installed on
// the point property (_qobjectForBindings) and after evaluating the expression,
// the result is written to a value type virtual property, that contains the sub-index
// of the "x" property.
- QQmlPropertyData targetCorePropertyData = *property;
- if (_valueTypeProperty)
- targetCorePropertyData = QQmlPropertyPrivate::saveValueType(*_valueTypeProperty, _qobject->metaObject(), property->coreIndex, engine);
+ QQmlBinding *qmlBinding;
+ if (_valueTypeProperty) {
+ qmlBinding = QQmlBinding::create(_valueTypeProperty, function, _scopeObject, context);
+ qmlBinding->setTarget(_bindingTarget, *_valueTypeProperty, property);
+ } else {
+ qmlBinding = QQmlBinding::create(property, function, _scopeObject, context);
+ qmlBinding->setTarget(_bindingTarget, *property, nullptr);
+ }
sharedState->allCreatedBindings.push(QQmlAbstractBinding::Ptr(qmlBinding));
- qmlBinding->setTarget(_bindingTarget, targetCorePropertyData);
-
- if (targetCorePropertyData.isAlias()) {
+ if (property->isAlias()) {
QQmlPropertyPrivate::setBinding(qmlBinding, QQmlPropertyPrivate::DontEnable);
} else {
qmlBinding->addToObject();
@@ -837,7 +828,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
if (!_valueTypeProperty) {
QQmlData *targetDeclarativeData = QQmlData::get(_bindingTarget);
Q_ASSERT(targetDeclarativeData);
- targetDeclarativeData->setPendingBindingBit(_bindingTarget, property->coreIndex);
+ targetDeclarativeData->setPendingBindingBit(_bindingTarget, property->coreIndex());
}
}
}
@@ -850,15 +841,16 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
QQmlType *type = qmlTypeForObject(createdSubObject);
Q_ASSERT(type);
- QQmlPropertyData targetCorePropertyData = *property;
- if (_valueTypeProperty)
- targetCorePropertyData = QQmlPropertyPrivate::saveValueType(*_valueTypeProperty, _qobject->metaObject(), property->coreIndex, engine);
-
int valueSourceCast = type->propertyValueSourceCast();
if (valueSourceCast != -1) {
QQmlPropertyValueSource *vs = reinterpret_cast<QQmlPropertyValueSource *>(reinterpret_cast<char *>(createdSubObject) + valueSourceCast);
QObject *target = createdSubObject->parent();
- vs->setTarget(QQmlPropertyPrivate::restore(target, targetCorePropertyData, context));
+ QQmlProperty prop;
+ if (_valueTypeProperty)
+ prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty, property, context);
+ else
+ prop = QQmlPropertyPrivate::restore(target, *property, nullptr, context);
+ vs->setTarget(prop);
return true;
}
int valueInterceptorCast = type->propertyValueInterceptorCast();
@@ -866,25 +858,36 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
QQmlPropertyValueInterceptor *vi = reinterpret_cast<QQmlPropertyValueInterceptor *>(reinterpret_cast<char *>(createdSubObject) + valueInterceptorCast);
QObject *target = createdSubObject->parent();
- if (targetCorePropertyData.isAlias()) {
- int propIndex;
- QQmlPropertyPrivate::findAliasTarget(target, targetCorePropertyData.coreIndex, &target, &propIndex);
+ QQmlPropertyIndex propertyIndex;
+ if (property->isAlias()) {
+ QQmlPropertyIndex originalIndex(property->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
+ QQmlPropertyIndex propIndex;
+ QQmlPropertyPrivate::findAliasTarget(target, originalIndex, &target, &propIndex);
QQmlData *data = QQmlData::get(target);
if (!data || !data->propertyCache) {
qWarning() << "can't resolve property alias for 'on' assignment";
return false;
}
- targetCorePropertyData = *data->propertyCache->property(propIndex);
- }
- QQmlProperty prop =
- QQmlPropertyPrivate::restore(target, targetCorePropertyData, context);
+ // we can't have aliasses on subproperties of value types, so:
+ QQmlPropertyData targetPropertyData = *data->propertyCache->property(propIndex.coreIndex());
+ auto prop = QQmlPropertyPrivate::restore(target, targetPropertyData, nullptr, context);
+ vi->setTarget(prop);
+ propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
+ } else {
+ QQmlProperty prop;
+ if (_valueTypeProperty)
+ prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty, property, context);
+ else
+ prop = QQmlPropertyPrivate::restore(target, *property, nullptr, context);
+ vi->setTarget(prop);
+ propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
+ }
- vi->setTarget(prop);
QQmlInterceptorMetaObject *mo = QQmlInterceptorMetaObject::get(target);
if (!mo)
mo = new QQmlInterceptorMetaObject(target, QQmlData::get(target)->propertyCache);
- mo->registerInterceptor(prop.index(), QQmlPropertyPrivate::valueTypeCoreIndex(prop), vi);
+ mo->registerInterceptor(propertyIndex, vi);
return true;
}
return false;
@@ -902,7 +905,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
return false;
}
- QMetaMethod signalMethod = _qobject->metaObject()->method(property->coreIndex);
+ QMetaMethod signalMethod = _qobject->metaObject()->method(property->coreIndex());
if (!QMetaObject::checkConnectArgs(signalMethod, method)) {
recordError(binding->valueLocation,
tr("Cannot connect mismatched signal/slot %1 %vs. %2")
@@ -911,33 +914,33 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
return false;
}
- QQmlPropertyPrivate::connect(_qobject, property->coreIndex, createdSubObject, method.methodIndex());
+ QQmlPropertyPrivate::connect(_qobject, property->coreIndex(), createdSubObject, method.methodIndex());
return true;
}
- QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
+ QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor |
+ QQmlPropertyData::RemoveBindingOnAliasWrite;
int propertyWriteStatus = -1;
void *argv[] = { 0, 0, &propertyWriteStatus, &propertyWriteFlags };
- if (const char *iid = QQmlMetaType::interfaceIId(property->propType)) {
+ if (const char *iid = QQmlMetaType::interfaceIId(property->propType())) {
void *ptr = createdSubObject->qt_metacast(iid);
if (ptr) {
argv[0] = &ptr;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex(), argv);
} else {
recordError(binding->location, tr("Cannot assign object to interface property"));
return false;
}
- } else if (property->propType == QMetaType::QVariant) {
+ } else if (property->propType() == QMetaType::QVariant) {
if (property->isVarProperty()) {
QV4::Scope scope(v4);
QV4::ScopedValue wrappedObject(scope, QV4::QObjectWrapper::wrap(QV8Engine::getV4(engine), createdSubObject));
- _vmeMetaObject->setVMEProperty(property->coreIndex, wrappedObject);
+ _vmeMetaObject->setVMEProperty(property->coreIndex(), wrappedObject);
} else {
QVariant value = QVariant::fromValue(createdSubObject);
argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex(), argv);
}
} else if (property->isQList()) {
Q_ASSERT(_currentList.object);
@@ -945,7 +948,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
void *itemToAdd = createdSubObject;
const char *iid = 0;
- int listItemType = QQmlEnginePrivate::get(engine)->listType(property->propType);
+ int listItemType = QQmlEnginePrivate::get(engine)->listType(property->propType());
if (listItemType != -1)
iid = QQmlMetaType::interfaceIId(listItemType);
if (iid)
@@ -961,7 +964,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
} else {
// pointer compatibility was tested in QQmlPropertyValidator at type compile time
argv[0] = &createdSubObject;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex(), argv);
}
return true;
}
@@ -981,9 +984,9 @@ void QQmlObjectCreator::setupFunctions()
QV4::ScopedValue function(scope);
QV4::ScopedContext qmlContext(scope, currentQmlContext());
- const quint32 *functionIdx = _compiledObject->functionOffsetTable();
+ const QV4::CompiledData::LEUInt32 *functionIdx = _compiledObject->functionOffsetTable();
for (quint32 i = 0; i < _compiledObject->nFunctions; ++i, ++functionIdx) {
- QV4::Function *runtimeFunction = compiledData->compilationUnit->runtimeFunctions[*functionIdx];
+ QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[*functionIdx];
const QString name = runtimeFunction->name()->toQString();
QQmlPropertyData *property = _propertyCache->property(name, _qobject, context);
@@ -991,14 +994,14 @@ void QQmlObjectCreator::setupFunctions()
continue;
function = QV4::FunctionObject::createScriptFunction(qmlContext, runtimeFunction);
- _vmeMetaObject->setVmeMethod(property->coreIndex, function);
+ _vmeMetaObject->setVmeMethod(property->coreIndex(), function);
}
}
void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location, const QString &description)
{
QQmlError error;
- error.setUrl(compiledData->compilationUnit->url());
+ error.setUrl(compilationUnit->url());
error.setLine(location.line);
error.setColumn(location.column);
error.setDescription(description);
@@ -1035,26 +1038,34 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
if (obj->flags & QV4::CompiledData::Object::IsComponent) {
isComponent = true;
- QQmlComponent *component = new QQmlComponent(engine, compiledData, index, parent);
+ QQmlComponent *component = new QQmlComponent(engine, compilationUnit, index, parent);
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
- compiledData, obj, QStringLiteral("<component>"), context->url()));
+ compilationUnit, obj, QStringLiteral("<component>"), context->url()));
QQmlComponentPrivate::get(component)->creationContext = context;
instance = component;
ddata = QQmlData::get(instance, /*create*/true);
} else {
- QQmlCompiledData::TypeReference *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
+ QV4::CompiledData::ResolvedTypeReference *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
Q_ASSERT(typeRef);
installPropertyCache = !typeRef->isFullyDynamicType;
QQmlType *type = typeRef->type;
if (type) {
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
- compiledData, obj, type->qmlTypeName(), context->url()));
- instance = type->create();
+ compilationUnit, obj, type->qmlTypeName(), context->url()));
+
+ void *ddataMemory = 0;
+ type->create(&instance, &ddataMemory, sizeof(QQmlData));
if (!instance) {
recordError(obj->location, tr("Unable to create object of type %1").arg(stringAt(obj->inheritedTypeNameIndex)));
return 0;
}
+ {
+ QQmlData *ddata = new (ddataMemory) QQmlData;
+ ddata->ownMemory = false;
+ QObjectPrivate::get(instance)->declarativeData = ddata;
+ }
+
const int parserStatusCast = type->parserStatusCast();
if (parserStatusCast != -1)
parserStatus = reinterpret_cast<QQmlParserStatus*>(reinterpret_cast<char *>(instance) + parserStatusCast);
@@ -1069,17 +1080,17 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
sharedState->allCreatedObjects.push(instance);
} else {
- Q_ASSERT(typeRef->component);
+ Q_ASSERT(typeRef->compilationUnit);
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
- compiledData, obj, typeRef->component->compilationUnit->fileName(),
+ compilationUnit, obj, typeRef->compilationUnit->fileName(),
context->url()));
- if (typeRef->component->compilationUnit->data->isSingleton())
+ if (typeRef->compilationUnit->data->isSingleton())
{
recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex)));
return 0;
}
- QQmlObjectCreator subCreator(context, typeRef->component, sharedState.data());
+ QQmlObjectCreator subCreator(context, typeRef->compilationUnit, sharedState.data());
instance = subCreator.create();
if (!instance) {
errors += subCreator.errors;
@@ -1127,7 +1138,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
if (customParser && obj->flags & QV4::CompiledData::Object::HasCustomParserBindings) {
customParser->engine = QQmlEnginePrivate::get(engine);
- customParser->imports = compiledData->compilationUnit->importCache;
+ customParser->imports = compilationUnit->importCache;
QList<const QV4::CompiledData::Binding *> bindings;
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
@@ -1137,7 +1148,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
bindings << binding;
}
}
- customParser->applyBindings(instance, compiledData->compilationUnit.data(), bindings);
+ customParser->applyBindings(instance, compilationUnit, bindings);
customParser->engine = 0;
customParser->imports = (QQmlTypeNameCache*)0;
@@ -1148,7 +1159,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
return instance;
}
- QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.at(index).data();
+ QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches->at(index);
Q_ASSERT(!cache.isNull());
if (installPropertyCache) {
if (ddata->propertyCache)
@@ -1193,9 +1204,9 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
continue;
QQmlData *data = QQmlData::get(b->targetObject());
Q_ASSERT(data);
- data->clearPendingBindingBit(b->targetPropertyIndex());
- b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::DontRemoveBinding);
+ data->clearPendingBindingBit(b->targetPropertyIndex().coreIndex());
+ b->setEnabled(true, QQmlPropertyData::BypassInterceptor |
+ QQmlPropertyData::DontRemoveBinding);
if (watcher.hasRecursed() || interrupt.shouldInterrupt())
return 0;
@@ -1279,14 +1290,13 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
QV4::Scope valueScope(v4);
QV4::ScopedValue scopeObjectProtector(valueScope);
- QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.at(_compiledObjectIndex).data();
+ QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches->at(_compiledObjectIndex);
QQmlVMEMetaObject *vmeMetaObject = 0;
- const bool needVMEMetaObject = propertyCaches.at(_compiledObjectIndex).flag();
- if (needVMEMetaObject) {
+ if (propertyCaches->needsVMEMetaObject(_compiledObjectIndex)) {
Q_ASSERT(!cache.isNull());
// install on _object
- vmeMetaObject = new QQmlVMEMetaObject(_qobject, cache, compiledData->compilationUnit, _compiledObjectIndex);
+ vmeMetaObject = new QQmlVMEMetaObject(_qobject, cache, compilationUnit, _compiledObjectIndex);
if (_ddata->propertyCache)
_ddata->propertyCache->release();
_ddata->propertyCache = cache;
@@ -1304,8 +1314,8 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
if (_compiledObject->flags & QV4::CompiledData::Object::HasDeferredBindings) {
QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
deferData->deferredIdx = _compiledObjectIndex;
- deferData->compiledData = compiledData;
- deferData->compiledData->addref();
+ deferData->compilationUnit = compilationUnit;
+ deferData->compilationUnit->addref();
deferData->context = context;
_ddata->deferredData = deferData;
}
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index f51cf3a2ca..e3312f9df5 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -53,7 +53,6 @@
#include <private/qqmlimport_p.h>
#include <private/qqmltypenamecache_p.h>
#include <private/qv4compileddata_p.h>
-#include <private/qqmlcompiler_p.h>
#include <private/qqmltypecompiler_p.h>
#include <private/qfinitestack_p.h>
#include <private/qrecursionwatcher_p.h>
@@ -66,7 +65,6 @@ QT_BEGIN_NAMESPACE
class QQmlAbstractBinding;
struct QQmlTypeCompiler;
class QQmlInstantiationInterrupt;
-struct QQmlVmeProfiler;
struct QQmlObjectCreatorSharedState : public QSharedData
{
@@ -86,7 +84,7 @@ class QQmlObjectCreator
{
Q_DECLARE_TR_FUNCTIONS(QQmlObjectCreator)
public:
- QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlContextData *creationContext, void *activeVMEDataForRootContext = 0);
+ QQmlObjectCreator(QQmlContextData *parentContext, QV4::CompiledData::CompilationUnit *compilationUnit, QQmlContextData *creationContext, void *activeVMEDataForRootContext = 0);
~QQmlObjectCreator();
QObject *create(int subComponentIndex = -1, QObject *parent = 0, QQmlInstantiationInterrupt *interrupt = 0);
@@ -104,7 +102,7 @@ public:
QFiniteStack<QPointer<QObject> > &allCreatedObjects() const { return sharedState->allCreatedObjects; }
private:
- QQmlObjectCreator(QQmlContextData *contextData, QQmlCompiledData *compiledData, QQmlObjectCreatorSharedState *inheritedSharedState);
+ QQmlObjectCreator(QQmlContextData *contextData, QV4::CompiledData::CompilationUnit *compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState);
void init(QQmlContextData *parentContext);
@@ -136,12 +134,12 @@ private:
QQmlEngine *engine;
QV4::ExecutionEngine *v4;
- QQmlCompiledData *compiledData;
+ QV4::CompiledData::CompilationUnit *compilationUnit;
const QV4::CompiledData::Unit *qmlUnit;
QQmlGuardedContextData parentContext;
QQmlContextData *context;
- const QHash<int, QQmlCompiledData::TypeReference*> &resolvedTypes;
- const QQmlPropertyCacheVector &propertyCaches;
+ const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
+ const QQmlPropertyCacheVector *propertyCaches;
QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState;
bool topLevelCreator;
void *activeVMEDataForRootContext;
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index 22c4072aec..49f02476a2 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -278,7 +278,7 @@ int QQmlOpenMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void *
propertyRead(propId);
*reinterpret_cast<QVariant *>(a[0]) = d->getData(propId);
} else if (c == QMetaObject::WriteProperty) {
- if (propId <= d->data.count() || d->data[propId].first != *reinterpret_cast<QVariant *>(a[0])) {
+ if (propId >= d->data.count() || d->data.at(propId).first != *reinterpret_cast<QVariant *>(a[0])) {
propertyWrite(propId);
QPair<QVariant, bool> &prop = d->getDataRef(propId);
prop.first = propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0]));
diff --git a/src/qml/qml/qqmlopenmetaobject_p.h b/src/qml/qml/qqmlopenmetaobject_p.h
index f1562131fc..183baec941 100644
--- a/src/qml/qml/qqmlopenmetaobject_p.h
+++ b/src/qml/qml/qqmlopenmetaobject_p.h
@@ -122,8 +122,8 @@ public:
void emitPropertyNotification(const QByteArray &propertyName);
protected:
- virtual int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a);
- virtual int createProperty(const char *, const char *);
+ int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) override;
+ int createProperty(const char *, const char *) override;
virtual void propertyRead(int);
virtual void propertyWrite(int);
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index df2ff05de1..c62fef7c3d 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -42,6 +42,7 @@
#include "qqml.h"
#include "qqmlbinding_p.h"
+#include "qqmlboundsignal_p.h"
#include "qqmlcontext.h"
#include "qqmlcontext_p.h"
#include "qqmlboundsignal_p.h"
@@ -50,7 +51,6 @@
#include "qqmldata_p.h"
#include "qqmlstringconverters_p.h"
#include "qqmllist_p.h"
-#include "qqmlcompiler_p.h"
#include "qqmlvmemetaobject_p.h"
#include "qqmlexpression_p.h"
#include "qqmlvaluetypeproxybinding_p.h"
@@ -291,9 +291,9 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
if (property->isFunction())
return; // Not an object property
- if (ii == (path.count() - 2) && QQmlValueTypeFactory::isValueType(property->propType)) {
+ if (ii == (path.count() - 2) && QQmlValueTypeFactory::isValueType(property->propType())) {
// We're now at a value type property
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType);
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType());
if (!valueTypeMetaObject) return; // Not a value type
int idx = valueTypeMetaObject->indexOfProperty(path.last().toUtf8().constData());
@@ -301,24 +301,21 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
QMetaProperty vtProp = valueTypeMetaObject->property(idx);
- Q_ASSERT(QQmlPropertyData::flagsForProperty(vtProp) <= QQmlPropertyData::ValueTypeFlagMask);
Q_ASSERT(vtProp.userType() <= 0x0000FFFF);
Q_ASSERT(idx <= 0x0000FFFF);
object = currentObject;
core = *property;
- core.setFlags(core.getFlags() | QQmlPropertyData::IsValueTypeVirtual);
- core.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp);
- core.valueTypePropType = vtProp.userType();
- core.valueTypeCoreIndex = idx;
+ valueTypeData.setFlags(QQmlPropertyData::flagsForProperty(vtProp));
+ valueTypeData.setPropType(vtProp.userType());
+ valueTypeData.setCoreIndex(idx);
return;
} else {
if (!property->isQObject())
return; // Not an object property
- void *args[] = { &currentObject, 0 };
- QMetaObject::metacall(currentObject, QMetaObject::ReadProperty, property->coreIndex, args);
+ property->readProperty(currentObject, &currentObject);
if (!currentObject) return; // No value
}
@@ -358,9 +355,9 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
while (d && d->isFunction())
d = ddata->propertyCache->overrideData(d);
- if (d && d->notifyIndex != -1) {
+ if (d && d->notifyIndex() != -1) {
object = currentObject;
- core = *ddata->propertyCache->signal(d->notifyIndex);
+ core = *ddata->propertyCache->signal(d->notifyIndex());
return;
}
}
@@ -397,7 +394,7 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
int QQmlPropertyPrivate::signalIndex() const
{
Q_ASSERT(type() == QQmlProperty::SignalProperty);
- QMetaMethod m = object->metaObject()->method(core.coreIndex);
+ QMetaMethod m = object->metaObject()->method(core.coreIndex());
return QMetaObjectPrivate::signalIndex(m);
}
@@ -473,11 +470,11 @@ const char *QQmlProperty::propertyTypeName() const
if (!d)
return 0;
if (d->isValueType()) {
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d->core.propType);
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d->core.propType());
Q_ASSERT(valueTypeMetaObject);
- return valueTypeMetaObject->property(d->core.valueTypeCoreIndex).typeName();
+ return valueTypeMetaObject->property(d->valueTypeData.coreIndex()).typeName();
} else if (d->object && type() & Property && d->core.isValid()) {
- return d->object->metaObject()->property(d->core.coreIndex).typeName();
+ return d->object->metaObject()->property(d->core.coreIndex()).typeName();
} else {
return 0;
}
@@ -494,11 +491,8 @@ bool QQmlProperty::operator==(const QQmlProperty &other) const
// category is intentially omitted here as it is generated
// from the other members
return d->object == other.d->object &&
- d->core.coreIndex == other.d->core.coreIndex &&
- d->core.isValueTypeVirtual() == other.d->core.isValueTypeVirtual() &&
- (!d->core.isValueTypeVirtual() ||
- (d->core.valueTypeCoreIndex == other.d->core.valueTypeCoreIndex &&
- d->core.valueTypePropType == other.d->core.valueTypePropType));
+ d->core.coreIndex() == other.d->core.coreIndex() &&
+ d->valueTypeData.coreIndex() == other.d->valueTypeData.coreIndex();
}
/*!
@@ -512,16 +506,16 @@ int QQmlProperty::propertyType() const
bool QQmlPropertyPrivate::isValueType() const
{
- return core.isValueTypeVirtual();
+ return valueTypeData.isValid();
}
int QQmlPropertyPrivate::propertyType() const
{
uint type = this->type();
if (isValueType()) {
- return core.valueTypePropType;
+ return valueTypeData.propType();
} else if (type & QQmlProperty::Property) {
- return core.propType;
+ return core.propType();
} else {
return QVariant::Invalid;
}
@@ -610,7 +604,7 @@ bool QQmlProperty::isDesignable() const
if (!d)
return false;
if (type() & Property && d->core.isValid() && d->object)
- return d->object->metaObject()->property(d->core.coreIndex).isDesignable();
+ return d->object->metaObject()->property(d->core.coreIndex()).isDesignable();
else
return false;
}
@@ -650,15 +644,11 @@ QString QQmlProperty::name() const
// ###
if (!d->object) {
} else if (d->isValueType()) {
- QString rv = d->core.name(d->object) + QLatin1Char('.');
-
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d->core.propType);
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d->core.propType());
Q_ASSERT(valueTypeMetaObject);
- const char *vtName = valueTypeMetaObject->property(d->core.valueTypeCoreIndex).name();
- rv += QString::fromUtf8(vtName);
-
- d->nameCache = rv;
+ const char *vtName = valueTypeMetaObject->property(d->valueTypeData.coreIndex()).name();
+ d->nameCache = d->core.name(d->object) + QLatin1Char('.') + QString::fromUtf8(vtName);
} else if (type() & SignalProperty) {
QString name = QLatin1String("on") + d->core.name(d->object);
name[2] = name.at(2).toUpper();
@@ -681,7 +671,7 @@ QMetaProperty QQmlProperty::property() const
if (!d)
return QMetaProperty();
if (type() & Property && d->core.isValid() && d->object)
- return d->object->metaObject()->property(d->core.coreIndex);
+ return d->object->metaObject()->property(d->core.coreIndex());
else
return QMetaProperty();
}
@@ -695,7 +685,7 @@ QMetaMethod QQmlProperty::method() const
if (!d)
return QMetaMethod();
if (type() & SignalProperty && d->object)
- return d->object->metaObject()->method(d->core.coreIndex);
+ return d->object->metaObject()->method(d->core.coreIndex());
else
return QMetaMethod();
}
@@ -710,7 +700,8 @@ QQmlPropertyPrivate::binding(const QQmlProperty &that)
if (!that.d || !that.isProperty() || !that.d->object)
return 0;
- return binding(that.d->object, that.d->core.encodedIndex());
+ QQmlPropertyIndex thatIndex(that.d->core.coreIndex(), that.d->valueTypeData.coreIndex());
+ return binding(that.d->object, thatIndex);
}
/*!
@@ -742,10 +733,10 @@ QQmlPropertyPrivate::setBinding(const QQmlProperty &that, QQmlAbstractBinding *n
setBinding(newBinding);
}
-static void removeOldBinding(QObject *object, int index, QQmlPropertyPrivate::BindingFlags flags = QQmlPropertyPrivate::None)
+static void removeOldBinding(QObject *object, QQmlPropertyIndex index, QQmlPropertyPrivate::BindingFlags flags = QQmlPropertyPrivate::None)
{
- int coreIndex;
- int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex);
+ int coreIndex = index.coreIndex();
+ int valueTypeIndex = index.valueTypeIndex();
QQmlData *data = QQmlData::get(object, false);
@@ -755,7 +746,8 @@ static void removeOldBinding(QObject *object, int index, QQmlPropertyPrivate::Bi
QQmlAbstractBinding::Ptr oldBinding;
oldBinding = data->bindings;
- while (oldBinding && oldBinding->targetPropertyIndex() != coreIndex)
+ while (oldBinding && (oldBinding->targetPropertyIndex().coreIndex() != coreIndex ||
+ oldBinding->targetPropertyIndex().hasValueTypeIndex()))
oldBinding = oldBinding->nextBinding();
if (!oldBinding)
@@ -777,12 +769,12 @@ void QQmlPropertyPrivate::removeBinding(QQmlAbstractBinding *b)
removeBinding(b->targetObject(), b->targetPropertyIndex());
}
-void QQmlPropertyPrivate::removeBinding(QObject *o, int index)
+void QQmlPropertyPrivate::removeBinding(QObject *o, QQmlPropertyIndex index)
{
Q_ASSERT(o);
QObject *target;
- int targetIndex;
+ QQmlPropertyIndex targetIndex;
findAliasTarget(o, index, &target, &targetIndex);
removeOldBinding(target, targetIndex);
}
@@ -792,11 +784,11 @@ void QQmlPropertyPrivate::removeBinding(const QQmlProperty &that)
if (!that.d || !that.isProperty() || !that.d->object)
return;
- removeBinding(that.d->object, that.d->core.encodedIndex());
+ removeBinding(that.d->object, that.d->encodedIndex());
}
QQmlAbstractBinding *
-QQmlPropertyPrivate::binding(QObject *object, int index)
+QQmlPropertyPrivate::binding(QObject *object, QQmlPropertyIndex index)
{
QQmlData *data = QQmlData::get(object);
if (!data)
@@ -804,19 +796,19 @@ QQmlPropertyPrivate::binding(QObject *object, int index)
findAliasTarget(object, index, &object, &index);
- int coreIndex;
- int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex);
+ const int coreIndex = index.coreIndex();
+ const int valueTypeIndex = index.valueTypeIndex();
if (!data->hasBindingBit(coreIndex))
return 0;
QQmlAbstractBinding *binding = data->bindings;
- while (binding && binding->targetPropertyIndex() != coreIndex)
+ while (binding && (binding->targetPropertyIndex().coreIndex() != coreIndex ||
+ binding->targetPropertyIndex().hasValueTypeIndex()))
binding = binding->nextBinding();
if (binding && valueTypeIndex != -1) {
if (binding->isValueTypeProxy()) {
- int index = QQmlPropertyData::encodeValueTypePropertyIndex(coreIndex, valueTypeIndex);
binding = static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index);
}
}
@@ -824,13 +816,14 @@ QQmlPropertyPrivate::binding(QObject *object, int index)
return binding;
}
-void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex,
- QObject **targetObject, int *targetBindingIndex)
+void QQmlPropertyPrivate::findAliasTarget(QObject *object, QQmlPropertyIndex bindingIndex,
+ QObject **targetObject,
+ QQmlPropertyIndex *targetBindingIndex)
{
QQmlData *data = QQmlData::get(object, false);
if (data) {
- int coreIndex;
- int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(bindingIndex, &coreIndex);
+ int coreIndex = bindingIndex.coreIndex();
+ int valueTypeIndex = bindingIndex.valueTypeIndex();
QQmlPropertyData *propertyData =
data->propertyCache?data->propertyCache->property(coreIndex):0;
@@ -842,11 +835,12 @@ void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex,
// This will either be a value type sub-reference or an alias to a value-type sub-reference not both
Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1);
- int aBindingIndex = aCoreIndex;
- if (aValueTypeIndex != -1)
- aBindingIndex = QQmlPropertyData::encodeValueTypePropertyIndex(aBindingIndex, aValueTypeIndex);
- else if (valueTypeIndex != -1)
- aBindingIndex = QQmlPropertyData::encodeValueTypePropertyIndex(aBindingIndex, valueTypeIndex);
+ QQmlPropertyIndex aBindingIndex(aCoreIndex);
+ if (aValueTypeIndex != -1) {
+ aBindingIndex = QQmlPropertyIndex(aCoreIndex, aValueTypeIndex);
+ } else if (valueTypeIndex != -1) {
+ aBindingIndex = QQmlPropertyIndex(aCoreIndex, valueTypeIndex);
+ }
findAliasTarget(aObject, aBindingIndex, targetObject, targetBindingIndex);
return;
@@ -859,16 +853,15 @@ void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex,
}
-void QQmlPropertyPrivate::setBinding(QQmlAbstractBinding *binding, BindingFlags flags, WriteFlags writeFlags)
+void QQmlPropertyPrivate::setBinding(QQmlAbstractBinding *binding, BindingFlags flags, QQmlPropertyData::WriteFlags writeFlags)
{
Q_ASSERT(binding);
QObject *object = binding->targetObject();
- int index = binding->targetPropertyIndex();
+ const QQmlPropertyIndex index = binding->targetPropertyIndex();
#ifndef QT_NO_DEBUG
- int coreIndex;
- QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex);
+ int coreIndex = index.coreIndex();
QQmlData *data = QQmlData::get(object, true);
if (data->propertyCache) {
QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex);
@@ -1027,42 +1020,40 @@ QVariant QQmlPropertyPrivate::readValueProperty()
{
if (isValueType()) {
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(core.propType);
+ QQmlValueType *valueType = QQmlValueTypeFactory::valueType(core.propType());
Q_ASSERT(valueType);
- valueType->read(object, core.coreIndex);
- return valueType->metaObject()->property(core.valueTypeCoreIndex).read(valueType);
+ valueType->read(object, core.coreIndex());
+ return valueType->metaObject()->property(valueTypeData.coreIndex()).read(valueType);
} else if (core.isQList()) {
QQmlListProperty<QObject> prop;
- void *args[] = { &prop, 0 };
- QMetaObject::metacall(object, QMetaObject::ReadProperty, core.coreIndex, args);
- return QVariant::fromValue(QQmlListReferencePrivate::init(prop, core.propType, engine));
+ core.readProperty(object, &prop);
+ return QVariant::fromValue(QQmlListReferencePrivate::init(prop, core.propType(), engine));
} else if (core.isQObject()) {
QObject *rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(object, QMetaObject::ReadProperty, core.coreIndex, args);
+ core.readProperty(object, &rv);
return QVariant::fromValue(rv);
} else {
- if (!core.propType) // Unregistered type
- return object->metaObject()->property(core.coreIndex).read(object);
+ if (!core.propType()) // Unregistered type
+ return object->metaObject()->property(core.coreIndex()).read(object);
QVariant value;
int status = -1;
void *args[] = { 0, &value, &status };
- if (core.propType == QMetaType::QVariant) {
+ if (core.propType() == QMetaType::QVariant) {
args[0] = &value;
} else {
- value = QVariant(core.propType, (void*)0);
+ value = QVariant(core.propType(), (void*)0);
args[0] = value.data();
}
- QMetaObject::metacall(object, QMetaObject::ReadProperty, core.coreIndex, args);
- if (core.propType != QMetaType::QVariant && args[0] != value.data())
- return QVariant((QVariant::Type)core.propType, args[0]);
+ core.readPropertyWithArgs(object, args);
+ if (core.propType() != QMetaType::QVariant && args[0] != value.data())
+ return QVariant((QVariant::Type)core.propType(), args[0]);
return value;
}
@@ -1148,40 +1139,30 @@ bool QQmlPropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx,
return status;
}
-bool QQmlPropertyPrivate::writeValueProperty(const QVariant &value, WriteFlags flags)
+bool QQmlPropertyPrivate::writeValueProperty(const QVariant &value, QQmlPropertyData::WriteFlags flags)
{
- return writeValueProperty(object, core, value, effectiveContext(), flags);
+ return writeValueProperty(object, core, valueTypeData, value, effectiveContext(), flags);
}
bool
QQmlPropertyPrivate::writeValueProperty(QObject *object,
const QQmlPropertyData &core,
+ const QQmlPropertyData &valueTypeData,
const QVariant &value,
- QQmlContextData *context, WriteFlags flags)
+ QQmlContextData *context,QQmlPropertyData::WriteFlags flags)
{
// Remove any existing bindings on this property
- if (!(flags & DontRemoveBinding) && object)
- removeBinding(object, core.encodedIndex());
+ if (!(flags & QQmlPropertyData::DontRemoveBinding) && object)
+ removeBinding(object, encodedIndex(core, valueTypeData));
bool rv = false;
- if (core.isValueTypeVirtual()) {
-
- QQmlValueType *writeBack = QQmlValueTypeFactory::valueType(core.propType);
- writeBack->read(object, core.coreIndex);
-
- QQmlPropertyData data = core;
- data.setFlags(QQmlPropertyData::Flag(core.valueTypeFlags));
- data.coreIndex = core.valueTypeCoreIndex;
- data.propType = core.valueTypePropType;
-
- rv = write(writeBack, data, value, context, flags);
-
- writeBack->write(object, core.coreIndex, flags);
-
+ if (valueTypeData.isValid()) {
+ QQmlValueType *writeBack = QQmlValueTypeFactory::valueType(core.propType());
+ writeBack->read(object, core.coreIndex());
+ rv = write(writeBack, valueTypeData, value, context, flags);
+ writeBack->write(object, core.coreIndex(), flags);
} else {
-
rv = write(object, core, value, context, flags);
-
}
return rv;
@@ -1190,173 +1171,158 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object,
bool QQmlPropertyPrivate::write(QObject *object,
const QQmlPropertyData &property,
const QVariant &value, QQmlContextData *context,
- WriteFlags flags)
+ QQmlPropertyData::WriteFlags flags)
{
- int coreIdx = property.coreIndex;
- int status = -1; //for dbus
+ const int propertyType = property.propType();
+ const int variantType = value.userType();
if (property.isEnum()) {
- QMetaProperty prop = object->metaObject()->property(property.coreIndex);
+ QMetaProperty prop = object->metaObject()->property(property.coreIndex());
QVariant v = value;
// Enum values come through the script engine as doubles
- if (value.userType() == QVariant::Double) {
+ if (variantType == QVariant::Double) {
double integral;
double fractional = std::modf(value.toDouble(), &integral);
if (qFuzzyIsNull(fractional))
v.convert(QVariant::Int);
}
- return writeEnumProperty(prop, coreIdx, object, v, flags);
+ return writeEnumProperty(prop, property.coreIndex(), object, v, flags);
}
- int propertyType = property.propType;
- int variantType = value.userType();
-
QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(context);
+ const bool isUrl = propertyType == QVariant::Url; // handled separately
+
+ // The cases below are in approximate order of likelyhood:
+ if (propertyType == variantType && !isUrl && propertyType != qMetaTypeId<QList<QUrl>>() && !property.isQList()) {
+ return property.writeProperty(object, const_cast<void *>(value.constData()), flags);
+ } else if (property.isQObject()) {
+ QQmlMetaObject valMo = rawMetaObjectForType(enginePriv, variantType);
+ if (valMo.isNull())
+ return false;
+ QObject *o = *static_cast<QObject *const *>(value.constData());
+ QQmlMetaObject propMo = rawMetaObjectForType(enginePriv, propertyType);
- if (propertyType == QVariant::Url) {
+ if (o)
+ valMo = o;
+ if (QQmlMetaObject::canConvert(valMo, propMo)) {
+ return property.writeProperty(object, &o, flags);
+ } else if (!o && QQmlMetaObject::canConvert(propMo, valMo)) {
+ // In the case of a null QObject, we assign the null if there is
+ // any change that the null variant type could be up or down cast to
+ // the property type.
+ return property.writeProperty(object, &o, flags);
+ } else {
+ return false;
+ }
+ } else if (value.canConvert(propertyType) && !isUrl && variantType != QVariant::String && propertyType != qMetaTypeId<QList<QUrl>>() && !property.isQList()) {
+ // common cases:
+ switch (propertyType) {
+ case QMetaType::Bool: {
+ bool b = value.toBool();
+ return property.writeProperty(object, &b, flags);
+ }
+ case QMetaType::Int: {
+ int i = value.toInt();
+ return property.writeProperty(object, &i, flags);
+ }
+ case QMetaType::Double: {
+ double d = value.toDouble();
+ return property.writeProperty(object, &d, flags);
+ }
+ case QMetaType::Float: {
+ float f = value.toFloat();
+ return property.writeProperty(object, &f, flags);
+ }
+ case QMetaType::QString: {
+ QString s = value.toString();
+ return property.writeProperty(object, &s, flags);
+ }
+ default: { // "fallback":
+ QVariant v = value;
+ v.convert(propertyType);
+ return property.writeProperty(object, const_cast<void *>(v.constData()), flags);
+ }
+ }
+ } else if (propertyType == qMetaTypeId<QVariant>()) {
+ return property.writeProperty(object, const_cast<QVariant *>(&value), flags);
+ } else if (isUrl) {
QUrl u;
- bool found = false;
if (variantType == QVariant::Url) {
u = value.toUrl();
- found = true;
} else if (variantType == QVariant::ByteArray) {
QString input(QString::fromUtf8(value.toByteArray()));
// Encoded dir-separators defeat QUrl processing - decode them first
input.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
u = QUrl(input);
- found = true;
} else if (variantType == QVariant::String) {
QString input(value.toString());
// Encoded dir-separators defeat QUrl processing - decode them first
input.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
u = QUrl(input);
- found = true;
- }
-
- if (!found)
- return false;
-
- if (context && u.isRelative() && !u.isEmpty())
- u = context->resolvedUrl(u);
- int status = -1;
- void *argv[] = { &u, 0, &status, &flags };
- QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv);
-
- } else if (propertyType == qMetaTypeId<QList<QUrl> >()) {
- QList<QUrl> urlSeq = resolvedUrlSequence(value, context).value<QList<QUrl> >();
- int status = -1;
- void *argv[] = { &urlSeq, 0, &status, &flags };
- QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv);
- } else if (variantType == propertyType) {
-
- void *a[] = { const_cast<void *>(value.constData()), 0, &status, &flags };
- QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
-
- } else if (qMetaTypeId<QVariant>() == propertyType) {
-
- void *a[] = { const_cast<QVariant *>(&value), 0, &status, &flags };
- QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
-
- } else if (property.isQObject()) {
-
- QQmlMetaObject valMo = rawMetaObjectForType(enginePriv, value.userType());
-
- if (valMo.isNull())
- return false;
-
- QObject *o = *(QObject *const *)value.constData();
- QQmlMetaObject propMo = rawMetaObjectForType(enginePriv, propertyType);
-
- if (o) valMo = o;
-
- if (QQmlMetaObject::canConvert(valMo, propMo)) {
- void *args[] = { &o, 0, &status, &flags };
- QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, args);
- } else if (!o && QQmlMetaObject::canConvert(propMo, valMo)) {
- // In the case of a null QObject, we assign the null if there is
- // any change that the null variant type could be up or down cast to
- // the property type.
- void *args[] = { &o, 0, &status, &flags };
- QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, args);
} else {
return false;
}
+ if (context && u.isRelative() && !u.isEmpty())
+ u = context->resolvedUrl(u);
+ return property.writeProperty(object, &u, flags);
+ } else if (propertyType == qMetaTypeId<QList<QUrl>>()) {
+ QList<QUrl> urlSeq = resolvedUrlSequence(value, context).value<QList<QUrl>>();
+ return property.writeProperty(object, &urlSeq, flags);
} else if (property.isQList()) {
-
QQmlMetaObject listType;
if (enginePriv) {
- listType = enginePriv->rawMetaObjectForType(enginePriv->listType(property.propType));
+ listType = enginePriv->rawMetaObjectForType(enginePriv->listType(property.propType()));
} else {
- QQmlType *type = QQmlMetaType::qmlType(QQmlMetaType::listType(property.propType));
- if (!type) return false;
+ QQmlType *type = QQmlMetaType::qmlType(QQmlMetaType::listType(property.propType()));
+ if (!type)
+ return false;
listType = type->baseMetaObject();
}
- if (listType.isNull()) return false;
+ if (listType.isNull())
+ return false;
QQmlListProperty<void> prop;
- void *args[] = { &prop, 0 };
- QMetaObject::metacall(object, QMetaObject::ReadProperty, coreIdx, args);
+ property.readProperty(object, &prop);
- if (!prop.clear) return false;
+ if (!prop.clear)
+ return false;
prop.clear(&prop);
- if (value.userType() == qMetaTypeId<QQmlListReference>()) {
+ if (variantType == qMetaTypeId<QQmlListReference>()) {
QQmlListReference qdlr = value.value<QQmlListReference>();
for (int ii = 0; ii < qdlr.count(); ++ii) {
QObject *o = qdlr.at(ii);
if (o && !QQmlMetaObject::canConvert(o, listType))
- o = 0;
- prop.append(&prop, (void *)o);
+ o = nullptr;
+ prop.append(&prop, o);
}
- } else if (value.userType() == qMetaTypeId<QList<QObject *> >()) {
+ } else if (variantType == qMetaTypeId<QList<QObject *> >()) {
const QList<QObject *> &list = qvariant_cast<QList<QObject *> >(value);
for (int ii = 0; ii < list.count(); ++ii) {
QObject *o = list.at(ii);
if (o && !QQmlMetaObject::canConvert(o, listType))
- o = 0;
- prop.append(&prop, (void *)o);
+ o = nullptr;
+ prop.append(&prop, o);
}
} else {
QObject *o = enginePriv?enginePriv->toQObject(value):QQmlMetaType::toQObject(value);
if (o && !QQmlMetaObject::canConvert(o, listType))
- o = 0;
- prop.append(&prop, (void *)o);
+ o = nullptr;
+ prop.append(&prop, o);
}
-
} else {
Q_ASSERT(variantType != propertyType);
bool ok = false;
QVariant v;
- if (variantType == QVariant::String) {
- const QString &str = value.toString();
- const bool targetIsChar = (propertyType == qMetaTypeId<QChar>()
- || propertyType == qMetaTypeId<char>()
- || propertyType == qMetaTypeId<unsigned char>());
- // If the string contains only one character and the target is a char, try converting it.
- if (targetIsChar) {
- if (str.size() != 1)
- return false; // We can only convert if the string contains exactly one character.
-
- const QChar &qChar = str.at(0);
- if (propertyType == qMetaTypeId<QChar>()) {
- v = qChar;
- ok = true;
- } else if (propertyType == qMetaTypeId<char>() || propertyType == qMetaTypeId<unsigned char>()) {
- const char c = qChar.toLatin1();
- v = c;
- ok = (qChar == c);
- }
- } else {
- v = QQmlStringConverters::variantFromString(str, propertyType, &ok);
- }
- }
+ if (variantType == QVariant::String)
+ v = QQmlStringConverters::variantFromString(value.toString(), propertyType, &ok);
if (!ok) {
v = value;
@@ -1368,7 +1334,8 @@ bool QQmlPropertyPrivate::write(QObject *object,
// successful conversion.
Q_ASSERT(v.userType() == propertyType);
ok = true;
- } else if ((uint)propertyType >= QVariant::UserType && variantType == QVariant::String) {
+ } else if (static_cast<uint>(propertyType) >= QVariant::UserType &&
+ variantType == QVariant::String) {
QQmlMetaType::StringConverter con = QQmlMetaType::customStringConverter(propertyType);
if (con) {
v = con(value.toString());
@@ -1411,8 +1378,7 @@ bool QQmlPropertyPrivate::write(QObject *object,
}
if (ok) {
- void *a[] = { const_cast<void *>(v.constData()), 0, &status, &flags};
- QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+ return property.writeProperty(object, const_cast<void *>(v.constData()), flags);
} else {
return false;
}
@@ -1428,10 +1394,9 @@ QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engi
return metaType.metaObject();
if (engine)
return engine->rawMetaObjectForType(userType);
- QQmlType *type = QQmlMetaType::qmlType(userType);
- if (type)
+ if (QQmlType *type = QQmlMetaType::qmlType(userType))
return QQmlMetaObject(type->baseMetaObject());
- return QQmlMetaObject((QObject*)0);
+ return QQmlMetaObject();
}
/*!
@@ -1505,7 +1470,7 @@ bool QQmlProperty::reset() const
{
if (isResettable()) {
void *args[] = { 0 };
- QMetaObject::metacall(d->object, QMetaObject::ResetProperty, d->core.coreIndex, args);
+ QMetaObject::metacall(d->object, QMetaObject::ResetProperty, d->core.coreIndex(), args);
return true;
} else {
return false;
@@ -1513,7 +1478,7 @@ bool QQmlProperty::reset() const
}
bool QQmlPropertyPrivate::write(const QQmlProperty &that,
- const QVariant &value, WriteFlags flags)
+ const QVariant &value, QQmlPropertyData::WriteFlags flags)
{
if (!that.d)
return false;
@@ -1530,7 +1495,7 @@ bool QQmlPropertyPrivate::write(const QQmlProperty &that,
bool QQmlProperty::hasNotifySignal() const
{
if (type() & Property && d->object) {
- return d->object->metaObject()->property(d->core.coreIndex).hasNotifySignal();
+ return d->object->metaObject()->property(d->core.coreIndex()).hasNotifySignal();
}
return false;
}
@@ -1560,7 +1525,7 @@ bool QQmlProperty::connectNotifySignal(QObject *dest, int method) const
if (!(type() & Property) || !d->object)
return false;
- QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex);
+ QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex());
if (prop.hasNotifySignal()) {
return QQmlPropertyPrivate::connect(d->object, prop.notifySignalIndex(), dest, method, Qt::DirectConnection);
} else {
@@ -1581,7 +1546,7 @@ bool QQmlProperty::connectNotifySignal(QObject *dest, const char *slot) const
if (!(type() & Property) || !d->object)
return false;
- QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex);
+ QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex());
if (prop.hasNotifySignal()) {
QByteArray signal('2' + prop.notifySignal().methodSignature());
return QObject::connect(d->object, signal.constData(), dest, slot);
@@ -1595,61 +1560,28 @@ bool QQmlProperty::connectNotifySignal(QObject *dest, const char *slot) const
*/
int QQmlProperty::index() const
{
- return d ? d->core.coreIndex : -1;
+ return d ? d->core.coreIndex() : -1;
}
-int QQmlPropertyPrivate::valueTypeCoreIndex(const QQmlProperty &that)
-{
- return that.d ? that.d->core.getValueTypeCoreIndex() : -1;
-}
-
-/*!
- Returns the "property index" for use in bindings. The top 16 bits are the value type
- offset, and 0 otherwise. The bottom 16 bits are the regular property index.
-*/
-int QQmlPropertyPrivate::bindingIndex(const QQmlProperty &that)
+QQmlPropertyIndex QQmlPropertyPrivate::propertyIndex(const QQmlProperty &that)
{
- if (!that.d)
- return -1;
- return bindingIndex(that.d->core);
-}
-
-int QQmlPropertyPrivate::bindingIndex(const QQmlPropertyData &that)
-{
- int rv = that.coreIndex;
- if (rv != -1 && that.isValueTypeVirtual())
- rv = rv | (that.valueTypeCoreIndex << 16);
- return rv;
-}
-
-QQmlPropertyData
-QQmlPropertyPrivate::saveValueType(const QQmlPropertyData &base,
- const QMetaObject *subObject, int subIndex,
- QQmlEngine *)
-{
- QMetaProperty subProp = subObject->property(subIndex);
-
- QQmlPropertyData core = base;
- core.setFlags(core.getFlags() | QQmlPropertyData::IsValueTypeVirtual);
- core.valueTypeFlags = QQmlPropertyData::flagsForProperty(subProp);
- core.valueTypeCoreIndex = subIndex;
- core.valueTypePropType = subProp.userType();
-
- return core;
+ return that.d ? that.d->encodedIndex() : QQmlPropertyIndex();
}
QQmlProperty
QQmlPropertyPrivate::restore(QObject *object, const QQmlPropertyData &data,
- QQmlContextData *ctxt)
+ const QQmlPropertyData *valueTypeData, QQmlContextData *ctxt)
{
QQmlProperty prop;
prop.d = new QQmlPropertyPrivate;
prop.d->object = object;
prop.d->context = ctxt;
- prop.d->engine = ctxt?ctxt->engine:0;
+ prop.d->engine = ctxt ? ctxt->engine : nullptr;
prop.d->core = data;
+ if (valueTypeData)
+ prop.d->valueTypeData = *valueTypeData;
return prop;
}
diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h
index 58fea9c239..2565ec0ce6 100644
--- a/src/qml/qml/qqmlproperty_p.h
+++ b/src/qml/qml/qqmlproperty_p.h
@@ -68,24 +68,23 @@ class QQmlJavaScriptExpression;
class Q_QML_PRIVATE_EXPORT QQmlPropertyPrivate : public QQmlRefCount
{
public:
- enum WriteFlag {
- BypassInterceptor = 0x01,
- DontRemoveBinding = 0x02,
- RemoveBindingOnAliasWrite = 0x04
- };
- Q_DECLARE_FLAGS(WriteFlags, WriteFlag)
-
QQmlContextData *context;
QPointer<QQmlEngine> engine;
QPointer<QObject> object;
QQmlPropertyData core;
+ QQmlPropertyData valueTypeData;
bool isNameCached:1;
QString nameCache;
QQmlPropertyPrivate();
+ QQmlPropertyIndex encodedIndex() const
+ { return encodedIndex(core, valueTypeData); }
+ static QQmlPropertyIndex encodedIndex(const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData)
+ { return QQmlPropertyIndex(core.coreIndex(), valueTypeData.coreIndex()); }
+
inline QQmlContextData *effectiveContext() const;
void initProperty(QObject *obj, const QString &name);
@@ -97,18 +96,18 @@ public:
QQmlProperty::PropertyTypeCategory propertyTypeCategory() const;
QVariant readValueProperty();
- bool writeValueProperty(const QVariant &, WriteFlags);
+ bool writeValueProperty(const QVariant &, QQmlPropertyData::WriteFlags);
static QQmlMetaObject rawMetaObjectForType(QQmlEnginePrivate *, int);
static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object,
const QVariant &value, int flags);
static bool writeValueProperty(QObject *,
- const QQmlPropertyData &,
+ const QQmlPropertyData &, const QQmlPropertyData &valueTypeData,
const QVariant &, QQmlContextData *,
- WriteFlags flags = 0);
+ QQmlPropertyData::WriteFlags flags = 0);
static bool write(QObject *, const QQmlPropertyData &, const QVariant &,
- QQmlContextData *, WriteFlags flags = 0);
- static void findAliasTarget(QObject *, int, QObject **, int *);
+ QQmlContextData *, QQmlPropertyData::WriteFlags flags = 0);
+ static void findAliasTarget(QObject *, QQmlPropertyIndex, QObject **, QQmlPropertyIndex *);
enum BindingFlag {
None = 0,
@@ -116,19 +115,15 @@ public:
};
Q_DECLARE_FLAGS(BindingFlags, BindingFlag)
- static void setBinding(QQmlAbstractBinding *binding, BindingFlags flags = None, WriteFlags writeFlags = DontRemoveBinding);
+ static void setBinding(QQmlAbstractBinding *binding, BindingFlags flags = None, QQmlPropertyData::WriteFlags writeFlags = QQmlPropertyData::DontRemoveBinding);
static void removeBinding(const QQmlProperty &that);
- static void removeBinding(QObject *o, int index);
+ static void removeBinding(QObject *o, QQmlPropertyIndex index);
static void removeBinding(QQmlAbstractBinding *b);
- static QQmlAbstractBinding *binding(QObject *, int index);
+ static QQmlAbstractBinding *binding(QObject *, QQmlPropertyIndex index);
- static QQmlPropertyData saveValueType(const QQmlPropertyData &,
- const QMetaObject *, int,
- QQmlEngine *);
- static QQmlProperty restore(QObject *,
- const QQmlPropertyData &,
- QQmlContextData *);
+ static QQmlProperty restore(QObject *, const QQmlPropertyData &, const QQmlPropertyData *,
+ QQmlContextData *);
int signalIndex() const;
@@ -144,10 +139,8 @@ public:
QQmlBoundSignalExpression *);
static void takeSignalExpression(const QQmlProperty &that,
QQmlBoundSignalExpression *);
- static bool write(const QQmlProperty &that, const QVariant &, WriteFlags);
- static int valueTypeCoreIndex(const QQmlProperty &that);
- static int bindingIndex(const QQmlProperty &that);
- static int bindingIndex(const QQmlPropertyData &that);
+ static bool write(const QQmlProperty &that, const QVariant &, QQmlPropertyData::WriteFlags);
+ static QQmlPropertyIndex propertyIndex(const QQmlProperty &that);
static QMetaMethod findSignalByName(const QMetaObject *mo, const QByteArray &);
static bool connect(const QObject *sender, int signal_index,
const QObject *receiver, int method_index,
@@ -157,7 +150,6 @@ public:
static QVariant resolvedUrlSequence(const QVariant &value, QQmlContextData *context);
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyPrivate::WriteFlags)
Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyPrivate::BindingFlags)
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 08d51ecfa1..337c37b5be 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -45,12 +45,12 @@
#include <private/qv8engine_p.h>
#include <private/qmetaobject_p.h>
-#include <private/qqmlaccessors_p.h>
#include <private/qmetaobjectbuilder_p.h>
#include <private/qv4value_p.h>
#include <QtCore/qdebug.h>
+#include <QtCore/QCryptographicHash>
#include <ctype.h> // for toupper
#include <limits.h>
@@ -85,51 +85,45 @@ static QQmlPropertyData::Flags fastFlagsForProperty(const QMetaProperty &p)
{
QQmlPropertyData::Flags flags;
- if (p.isConstant())
- flags |= QQmlPropertyData::IsConstant;
- if (p.isWritable())
- flags |= QQmlPropertyData::IsWritable;
- if (p.isResettable())
- flags |= QQmlPropertyData::IsResettable;
- if (p.isFinal())
- flags |= QQmlPropertyData::IsFinal;
+ flags.isConstant = p.isConstant();
+ flags.isWritable = p.isWritable();
+ flags.isResettable = p.isResettable();
+ flags.isFinal = p.isFinal();
+
if (p.isEnumType())
- flags |= QQmlPropertyData::IsEnumType;
+ flags.type = QQmlPropertyData::Flags::EnumType;
return flags;
}
// Flags that do depend on the property's QMetaProperty::userType() and thus are slow to
// load
-static QQmlPropertyData::Flags flagsForPropertyType(int propType, QQmlEngine *engine)
+static void flagsForPropertyType(int propType, QQmlEngine *engine, QQmlPropertyData::Flags &flags)
{
Q_ASSERT(propType != -1);
- QQmlPropertyData::Flags flags;
-
if (propType == QMetaType::QObjectStar) {
- flags |= QQmlPropertyData::IsQObjectDerived;
+ flags.type = QQmlPropertyData::Flags::QObjectDerivedType;
} else if (propType == QMetaType::QVariant) {
- flags |= QQmlPropertyData::IsQVariant;
- } else if (propType < (int)QVariant::UserType) {
+ flags.type = QQmlPropertyData::Flags::QVariantType;
+ } else if (propType < static_cast<int>(QVariant::UserType)) {
+ // nothing to do
} else if (propType == qMetaTypeId<QQmlBinding *>()) {
- flags |= QQmlPropertyData::IsQmlBinding;
+ flags.type = QQmlPropertyData::Flags::QmlBindingType;
} else if (propType == qMetaTypeId<QJSValue>()) {
- flags |= QQmlPropertyData::IsQJSValue;
+ flags.type = QQmlPropertyData::Flags::QJSValueType;
} else if (propType == qMetaTypeId<QQmlV4Handle>()) {
- flags |= QQmlPropertyData::IsV4Handle;
+ flags.type = QQmlPropertyData::Flags::V4HandleType;
} else {
QQmlMetaType::TypeCategory cat =
engine ? QQmlEnginePrivate::get(engine)->typeCategory(propType)
: QQmlMetaType::typeCategory(propType);
if (cat == QQmlMetaType::Object || QMetaType::typeFlags(propType) & QMetaType::PointerToQObject)
- flags |= QQmlPropertyData::IsQObjectDerived;
+ flags.type = QQmlPropertyData::Flags::QObjectDerivedType;
else if (cat == QQmlMetaType::List)
- flags |= QQmlPropertyData::IsQList;
+ flags.type = QQmlPropertyData::Flags::QListType;
}
-
- return flags;
}
static int metaObjectSignalCount(const QMetaObject *metaObject)
@@ -143,95 +137,107 @@ static int metaObjectSignalCount(const QMetaObject *metaObject)
QQmlPropertyData::Flags
QQmlPropertyData::flagsForProperty(const QMetaProperty &p, QQmlEngine *engine)
{
- return fastFlagsForProperty(p) | flagsForPropertyType(p.userType(), engine);
+ auto flags = fastFlagsForProperty(p);
+ flagsForPropertyType(p.userType(), engine, flags);
+ return flags;
}
void QQmlPropertyData::lazyLoad(const QMetaProperty &p)
{
- coreIndex = p.propertyIndex();
- notifyIndex = QMetaObjectPrivate::signalIndex(p.notifySignal());
+ setCoreIndex(p.propertyIndex());
+ setNotifyIndex(QMetaObjectPrivate::signalIndex(p.notifySignal()));
Q_ASSERT(p.revision() <= Q_INT16_MAX);
- revision = p.revision();
+ setRevision(p.revision());
- flags = fastFlagsForProperty(p);
+ setFlags(fastFlagsForProperty(p));
- int type = p.type();
+ int type = static_cast<int>(p.type());
if (type == QMetaType::QObjectStar) {
- propType = type;
- flags |= QQmlPropertyData::IsQObjectDerived;
+ setPropType(type);
+ _flags.type = Flags::QObjectDerivedType;
} else if (type == QMetaType::QVariant) {
- propType = type;
- flags |= QQmlPropertyData::IsQVariant;
+ setPropType(type);
+ _flags.type = Flags::QVariantType;
} else if (type == QVariant::UserType || type == -1) {
- propTypeName = p.typeName();
- flags |= QQmlPropertyData::NotFullyResolved;
+ _flags.notFullyResolved = true;
} else {
- propType = type;
+ setPropType(type);
}
}
void QQmlPropertyData::load(const QMetaProperty &p, QQmlEngine *engine)
{
- propType = p.userType();
- coreIndex = p.propertyIndex();
- notifyIndex = QMetaObjectPrivate::signalIndex(p.notifySignal());
- flags = fastFlagsForProperty(p) | flagsForPropertyType(propType, engine);
+ setPropType(p.userType());
+ setCoreIndex(p.propertyIndex());
+ setNotifyIndex(QMetaObjectPrivate::signalIndex(p.notifySignal()));
+ setFlags(fastFlagsForProperty(p));
+ flagsForPropertyType(propType(), engine, _flags);
Q_ASSERT(p.revision() <= Q_INT16_MAX);
- revision = p.revision();
+ setRevision(p.revision());
}
void QQmlPropertyData::load(const QMetaMethod &m)
{
- coreIndex = m.methodIndex();
- arguments = 0;
- flags |= IsFunction;
+ setCoreIndex(m.methodIndex());
+ setArguments(nullptr);
+
+ setPropType(m.returnType());
+
+ _flags.type = Flags::FunctionType;
if (m.methodType() == QMetaMethod::Signal)
- flags |= IsSignal;
- propType = m.returnType();
+ _flags.isSignal = true;
+ else if (m.methodType() == QMetaMethod::Constructor) {
+ _flags.isConstructor = true;
+ setPropType(QMetaType::QObjectStar);
+ }
if (m.parameterCount()) {
- flags |= HasArguments;
+ _flags.hasArguments = true;
if ((m.parameterCount() == 1) && (m.parameterTypes().first() == "QQmlV4Function*")) {
- flags |= IsV4Function;
+ _flags.isV4Function = true;
}
}
if (m.attributes() & QMetaMethod::Cloned)
- flags |= IsCloned;
+ _flags.isCloned = true;
Q_ASSERT(m.revision() <= Q_INT16_MAX);
- revision = m.revision();
+ setRevision(m.revision());
}
void QQmlPropertyData::lazyLoad(const QMetaMethod &m)
{
- coreIndex = m.methodIndex();
- arguments = 0;
- flags |= IsFunction;
+ setCoreIndex(m.methodIndex());
+ setPropType(QMetaType::Void);
+ setArguments(nullptr);
+ _flags.type = Flags::FunctionType;
if (m.methodType() == QMetaMethod::Signal)
- flags |= IsSignal;
- propType = QMetaType::Void;
+ _flags.isSignal = true;
+ else if (m.methodType() == QMetaMethod::Constructor) {
+ _flags.isConstructor = true;
+ setPropType(QMetaType::QObjectStar);
+ }
const char *returnType = m.typeName();
if (!returnType)
returnType = "\0";
if ((*returnType != 'v') || (qstrcmp(returnType+1, "oid") != 0)) {
- propTypeName = returnType;
- flags |= NotFullyResolved;
+ _flags.notFullyResolved = true;
}
- if (m.parameterCount()) {
- flags |= HasArguments;
- if ((m.parameterCount() == 1) && (m.parameterTypes().first() == "QQmlV4Function*")) {
- flags |= IsV4Function;
+ const int paramCount = m.parameterCount();
+ if (paramCount) {
+ _flags.hasArguments = true;
+ if ((paramCount == 1) && (m.parameterTypes().first() == "QQmlV4Function*")) {
+ _flags.isV4Function = true;
}
}
if (m.attributes() & QMetaMethod::Cloned)
- flags |= IsCloned;
+ _flags.isCloned = true;
Q_ASSERT(m.revision() <= Q_INT16_MAX);
- revision = m.revision();
+ setRevision(m.revision());
}
/*!
@@ -330,14 +336,14 @@ QQmlPropertyCache *QQmlPropertyCache::copyAndReserve(int propertyCount, int meth
\a notifyIndex MUST be in the signal index range (see QObjectPrivate::signalIndex()).
This is different from QMetaMethod::methodIndex().
*/
-void QQmlPropertyCache::appendProperty(const QString &name,
- quint32 flags, int coreIndex, int propType, int notifyIndex)
+void QQmlPropertyCache::appendProperty(const QString &name, QQmlPropertyData::Flags flags,
+ int coreIndex, int propType, int notifyIndex)
{
QQmlPropertyData data;
- data.propType = propType;
- data.coreIndex = coreIndex;
- data.notifyIndex = notifyIndex;
- data.flags = flags;
+ data.setPropType(propType);
+ data.setCoreIndex(coreIndex);
+ data.setNotifyIndex(notifyIndex);
+ data.setFlags(flags);
QQmlPropertyData *old = findNamedProperty(name);
if (old)
@@ -349,24 +355,25 @@ void QQmlPropertyCache::appendProperty(const QString &name,
setNamedProperty(name, index + propertyOffset(), propertyIndexCache.data() + index, (old != 0));
}
-void QQmlPropertyCache::appendSignal(const QString &name, quint32 flags, int coreIndex,
- const int *types, const QList<QByteArray> &names)
+void QQmlPropertyCache::appendSignal(const QString &name, QQmlPropertyData::Flags flags,
+ int coreIndex, const int *types,
+ const QList<QByteArray> &names)
{
QQmlPropertyData data;
- data.propType = QVariant::Invalid;
- data.coreIndex = coreIndex;
- data.flags = flags;
- data.arguments = 0;
+ data.setPropType(QVariant::Invalid);
+ data.setCoreIndex(coreIndex);
+ data.setFlags(flags);
+ data.setArguments(nullptr);
QQmlPropertyData handler = data;
- handler.flags |= QQmlPropertyData::IsSignalHandler;
+ handler._flags.isSignalHandler = true;
if (types) {
int argumentCount = *types;
QQmlPropertyCacheMethodArguments *args = createArgumentsObject(argumentCount, names);
::memcpy(args->arguments, types, (argumentCount + 1) * sizeof(int));
args->argumentsValid = true;
- data.arguments = args;
+ data.setArguments(args);
}
QQmlPropertyData *old = findNamedProperty(name);
@@ -380,28 +387,28 @@ void QQmlPropertyCache::appendSignal(const QString &name, quint32 flags, int cor
signalHandlerIndexCache.append(handler);
QString handlerName = QLatin1String("on") + name;
- handlerName[2] = handlerName[2].toUpper();
+ handlerName[2] = handlerName.at(2).toUpper();
setNamedProperty(name, methodIndex + methodOffset(), methodIndexCache.data() + methodIndex, (old != 0));
setNamedProperty(handlerName, signalHandlerIndex + signalOffset(), signalHandlerIndexCache.data() + signalHandlerIndex, (old != 0));
}
-void QQmlPropertyCache::appendMethod(const QString &name, quint32 flags, int coreIndex,
- const QList<QByteArray> &names)
+void QQmlPropertyCache::appendMethod(const QString &name, QQmlPropertyData::Flags flags,
+ int coreIndex, const QList<QByteArray> &names)
{
int argumentCount = names.count();
QQmlPropertyData data;
- data.propType = QMetaType::QVariant;
- data.coreIndex = coreIndex;
+ data.setPropType(QMetaType::QVariant);
+ data.setCoreIndex(coreIndex);
QQmlPropertyCacheMethodArguments *args = createArgumentsObject(argumentCount, names);
for (int ii = 0; ii < argumentCount; ++ii)
args->arguments[ii + 1] = QMetaType::QVariant;
args->argumentsValid = true;
- data.arguments = args;
+ data.setArguments(args);
- data.flags = flags;
+ data.setFlags(flags);
QQmlPropertyData *old = findNamedProperty(name);
if (old)
@@ -413,12 +420,6 @@ void QQmlPropertyCache::appendMethod(const QString &name, quint32 flags, int cor
setNamedProperty(name, methodIndex + methodOffset(), methodIndexCache.data() + methodIndex, (old != 0));
}
-// Returns this property cache's metaObject. May be null if it hasn't been created yet.
-const QMetaObject *QQmlPropertyCache::metaObject() const
-{
- return _metaObject;
-}
-
// Returns this property cache's metaObject, creating it if necessary.
const QMetaObject *QQmlPropertyCache::createMetaObject()
{
@@ -434,22 +435,11 @@ const QMetaObject *QQmlPropertyCache::createMetaObject()
return _metaObject;
}
-// Returns the name of the default property for this cache
-QString QQmlPropertyCache::defaultPropertyName() const
-{
- return _defaultPropertyName;
-}
-
QQmlPropertyData *QQmlPropertyCache::defaultProperty() const
{
return property(defaultPropertyName(), 0, 0);
}
-QQmlPropertyCache *QQmlPropertyCache::parent() const
-{
- return _parent;
-}
-
void QQmlPropertyCache::setParent(QQmlPropertyCache *newParent)
{
if (_parent == newParent)
@@ -460,30 +450,21 @@ void QQmlPropertyCache::setParent(QQmlPropertyCache *newParent)
_parent->addref();
}
-// Returns the first C++ type's QMetaObject - that is, the first QMetaObject not created by
-// QML
-const QMetaObject *QQmlPropertyCache::firstCppMetaObject() const
-{
- while (_parent && (_metaObject == 0 || _ownMetaObject))
- return _parent->firstCppMetaObject();
- return _metaObject;
-}
-
QQmlPropertyCache *
QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject,
- QQmlPropertyData::Flag propertyFlags,
- QQmlPropertyData::Flag methodFlags,
- QQmlPropertyData::Flag signalFlags)
+ QQmlPropertyData::Flags propertyFlags,
+ QQmlPropertyData::Flags methodFlags,
+ QQmlPropertyData::Flags signalFlags)
{
return copyAndAppend(metaObject, -1, propertyFlags, methodFlags, signalFlags);
}
QQmlPropertyCache *
QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject,
- int revision,
- QQmlPropertyData::Flag propertyFlags,
- QQmlPropertyData::Flag methodFlags,
- QQmlPropertyData::Flag signalFlags)
+ int revision,
+ QQmlPropertyData::Flags propertyFlags,
+ QQmlPropertyData::Flags methodFlags,
+ QQmlPropertyData::Flags signalFlags)
{
Q_ASSERT(QMetaObjectPrivate::get(metaObject)->revision >= 4);
@@ -500,10 +481,10 @@ QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject,
}
void QQmlPropertyCache::append(const QMetaObject *metaObject,
- int revision,
- QQmlPropertyData::Flag propertyFlags,
- QQmlPropertyData::Flag methodFlags,
- QQmlPropertyData::Flag signalFlags)
+ int revision,
+ QQmlPropertyData::Flags propertyFlags,
+ QQmlPropertyData::Flags methodFlags,
+ QQmlPropertyData::Flags signalFlags)
{
Q_UNUSED(revision);
@@ -518,34 +499,16 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
int signalCount = metaObjectSignalCount(metaObject);
int classInfoCount = QMetaObjectPrivate::get(metaObject)->classInfoCount;
- QQmlAccessorProperties::Properties accessorProperties;
-
if (classInfoCount) {
int classInfoOffset = metaObject->classInfoOffset();
- bool hasFastProperty = false;
for (int ii = 0; ii < classInfoCount; ++ii) {
int idx = ii + classInfoOffset;
-
- if (0 == qstrcmp(metaObject->classInfo(idx).name(), "qt_HasQmlAccessors")) {
- hasFastProperty = true;
- } else if (0 == qstrcmp(metaObject->classInfo(idx).name(), "DefaultProperty")) {
- _defaultPropertyName = QString::fromUtf8(metaObject->classInfo(idx).value());
+ QMetaClassInfo mci = metaObject->classInfo(idx);
+ const char *name = mci.name();
+ if (0 == qstrcmp(name, "DefaultProperty")) {
+ _defaultPropertyName = QString::fromUtf8(mci.value());
}
}
-
- if (hasFastProperty) {
- accessorProperties = QQmlAccessorProperties::properties(metaObject);
- if (accessorProperties.count == 0)
- qFatal("QQmlPropertyCache: %s has FastProperty class info, but has not "
- "installed property accessors", metaObject->className());
- } else {
-#ifndef QT_NO_DEBUG
- accessorProperties = QQmlAccessorProperties::properties(metaObject);
- if (accessorProperties.count != 0)
- qFatal("QQmlPropertyCache: %s has fast property accessors, but is missing "
- "FastProperty class info", metaObject->className());
-#endif
- }
}
//Used to block access to QObject::destroyed() and QObject::deleteLater() from QML
@@ -584,23 +547,21 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
QQmlPropertyData *data = &methodIndexCache[ii - methodIndexCacheStart];
QQmlPropertyData *sigdata = 0;
- data->lazyLoad(m);
-
- if (data->isSignal())
- data->flags |= signalFlags;
+ if (m.methodType() == QMetaMethod::Signal)
+ data->setFlags(signalFlags);
else
- data->flags |= methodFlags;
+ data->setFlags(methodFlags);
- if (!dynamicMetaObject)
- data->flags |= QQmlPropertyData::IsDirect;
+ data->lazyLoad(m);
+ data->_flags.isDirect = !dynamicMetaObject;
Q_ASSERT((allowedRevisionCache.count() - 1) < Q_INT16_MAX);
- data->metaObjectOffset = allowedRevisionCache.count() - 1;
+ data->setMetaObjectOffset(allowedRevisionCache.count() - 1);
if (data->isSignal()) {
sigdata = &signalHandlerIndexCache[signalHandlerIndex - signalHandlerIndexCacheStart];
*sigdata = *data;
- sigdata->flags |= QQmlPropertyData::IsSignalHandler;
+ sigdata->_flags.isSignalHandler = true;
}
QQmlPropertyData *old = 0;
@@ -612,7 +573,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
setNamedProperty(methodName, ii, data, (old != 0));
if (data->isSignal()) {
- QHashedString on(QStringLiteral("on") % methodName.at(0).toUpper() % methodName.midRef(1));
+ QHashedString on(QLatin1String("on") % methodName.at(0).toUpper() % methodName.midRef(1));
setNamedProperty(on, ii, sigdata, (old != 0));
++signalHandlerIndex;
}
@@ -641,8 +602,8 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
if (old) {
// We only overload methods in the same class, exactly like C++
- if (old->isFunction() && old->coreIndex >= methodOffset)
- data->flags |= QQmlPropertyData::IsOverload;
+ if (old->isFunction() && old->coreIndex() >= methodOffset)
+ data->_flags.isOverload = true;
data->markAsOverrideOf(old);
}
@@ -669,14 +630,13 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
QQmlPropertyData *data = &propertyIndexCache[ii - propertyIndexCacheStart];
+ data->setFlags(propertyFlags);
data->lazyLoad(p);
- data->flags |= propertyFlags;
- if (!dynamicMetaObject)
- data->flags |= QQmlPropertyData::IsDirect;
+ data->_flags.isDirect = !dynamicMetaObject;
Q_ASSERT((allowedRevisionCache.count() - 1) < Q_INT16_MAX);
- data->metaObjectOffset = allowedRevisionCache.count() - 1;
+ data->setMetaObjectOffset(allowedRevisionCache.count() - 1);
QQmlPropertyData *old = 0;
@@ -692,29 +652,40 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
setNamedProperty(propName, ii, data, (old != 0));
}
- QQmlAccessorProperties::Property *accessorProperty = accessorProperties.property(str);
-
- // Fast properties may not be overrides or revisioned
- Q_ASSERT(accessorProperty == 0 || (old == 0 && data->revision == 0));
+ bool isGadget = true;
+ for (const QMetaObject *it = metaObject; it != nullptr; it = it->superClass()) {
+ if (it == &QObject::staticMetaObject)
+ isGadget = false;
+ }
- if (accessorProperty) {
- data->flags |= QQmlPropertyData::HasAccessors;
- data->accessors = accessorProperty->accessors;
- } else if (old) {
+ if (isGadget) // always dispatch over a 'normal' meta-call so the QQmlValueType can intercept
+ data->_flags.isDirect = false;
+ else
+ data->trySetStaticMetaCallFunction(metaObject->d.static_metacall, ii - propOffset);
+ if (old)
data->markAsOverrideOf(old);
- }
}
}
void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
{
Q_ASSERT(data->notFullyResolved());
-
- data->propType = QMetaType::type(data->propTypeName);
+ data->_flags.notFullyResolved = false;
+
+ const QMetaObject *mo = firstCppMetaObject();
+ if (data->isFunction()) {
+ auto metaMethod = mo->method(data->coreIndex());
+ const char *retTy = metaMethod.typeName();
+ if (!retTy)
+ retTy = "\0";
+ data->setPropType(QMetaType::type(retTy));
+ } else {
+ auto metaProperty = mo->property(data->coreIndex());
+ data->setPropType(QMetaType::type(metaProperty.typeName()));
+ }
if (!data->isFunction()) {
- if (data->propType == QMetaType::UnknownType) {
- const QMetaObject *mo = _metaObject;
+ if (data->propType() == QMetaType::UnknownType) {
QQmlPropertyCache *p = _parent;
while (p && (!mo || _ownMetaObject)) {
mo = p->_metaObject;
@@ -722,22 +693,20 @@ void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
}
int propOffset = mo->propertyOffset();
- if (mo && data->coreIndex < propOffset + mo->propertyCount()) {
- while (data->coreIndex < propOffset) {
+ if (mo && data->coreIndex() < propOffset + mo->propertyCount()) {
+ while (data->coreIndex() < propOffset) {
mo = mo->superClass();
propOffset = mo->propertyOffset();
}
int registerResult = -1;
void *argv[] = { &registerResult };
- mo->static_metacall(QMetaObject::RegisterPropertyMetaType, data->coreIndex - propOffset, argv);
- data->propType = registerResult == -1 ? QMetaType::UnknownType : registerResult;
+ mo->static_metacall(QMetaObject::RegisterPropertyMetaType, data->coreIndex() - propOffset, argv);
+ data->setPropType(registerResult == -1 ? QMetaType::UnknownType : registerResult);
}
}
- data->flags |= flagsForPropertyType(data->propType, engine->qmlEngine());
+ flagsForPropertyType(data->propType(), engine->qmlEngine(), data->_flags);
}
-
- data->flags &= ~QQmlPropertyData::NotFullyResolved;
}
void QQmlPropertyCache::updateRecur(const QMetaObject *metaObject)
@@ -804,48 +773,6 @@ void QQmlPropertyCache::invalidate(const QMetaObject *metaObject)
}
}
-/*! \internal
- \a index MUST be in the signal index range (see QObjectPrivate::signalIndex()).
- This is different from QMetaMethod::methodIndex().
-*/
-QQmlPropertyData *
-QQmlPropertyCache::signal(int index) const
-{
- if (index < 0 || index >= (signalHandlerIndexCacheStart + signalHandlerIndexCache.count()))
- return 0;
-
- if (index < signalHandlerIndexCacheStart)
- return _parent->signal(index);
-
- QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&methodIndexCache.at(index - signalHandlerIndexCacheStart));
- Q_ASSERT(rv->isSignal() || rv->coreIndex == -1);
- return ensureResolved(rv);
-}
-
-int QQmlPropertyCache::methodIndexToSignalIndex(int index) const
-{
- if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.count()))
- return index;
-
- if (index < methodIndexCacheStart)
- return _parent->methodIndexToSignalIndex(index);
-
- return index - methodIndexCacheStart + signalHandlerIndexCacheStart;
-}
-
-QQmlPropertyData *
-QQmlPropertyCache::method(int index) const
-{
- if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.count()))
- return 0;
-
- if (index < methodIndexCacheStart)
- return _parent->method(index);
-
- QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&methodIndexCache.at(index - methodIndexCacheStart));
- return ensureResolved(rv);
-}
-
QQmlPropertyData *QQmlPropertyCache::findProperty(StringCache::ConstIterator it, QObject *object, QQmlContextData *context) const
{
QQmlData *data = (object ? QQmlData::get(object) : 0);
@@ -862,11 +789,11 @@ inline bool contextHasNoExtensions(QQmlContextData *context)
return (!context->parent || !context->parent->imports);
}
-inline int maximumIndexForProperty(QQmlPropertyData *prop, const QQmlVMEMetaObject *vmemo)
+inline int maximumIndexForProperty(QQmlPropertyData *prop, const int methodCount, const int signalCount, const int propertyCount)
{
- return (prop->isFunction() ? vmemo->methodCount()
- : prop->isSignalHandler() ? vmemo->signalCount()
- : vmemo->propertyCount());
+ return prop->isFunction() ? methodCount
+ : prop->isSignalHandler() ? signalCount
+ : propertyCount;
}
}
@@ -893,11 +820,15 @@ QQmlPropertyData *QQmlPropertyCache::findProperty(StringCache::ConstIterator it,
}
if (vmemo) {
+ const int methodCount = vmemo->methodCount();
+ const int signalCount = vmemo->signalCount();
+ const int propertyCount = vmemo->propertyCount();
+
// Ensure that the property we resolve to is accessible from this meta-object
do {
const StringCache::mapped_type &property(it.value());
- if (property.first < maximumIndexForProperty(property.second, vmemo)) {
+ if (property.first < maximumIndexForProperty(property.second, methodCount, signalCount, propertyCount)) {
// This property is available in the specified context
if (property.second->isFunction() || property.second->isSignalHandler()) {
// Prefer the earlier resolution
@@ -929,33 +860,25 @@ QString QQmlPropertyData::name(QObject *object) const
QString QQmlPropertyData::name(const QMetaObject *metaObject) const
{
- if (!metaObject || coreIndex == -1)
+ if (!metaObject || coreIndex() == -1)
return QString();
- if (flags & IsFunction) {
- QMetaMethod m = metaObject->method(coreIndex);
+ if (isFunction()) {
+ QMetaMethod m = metaObject->method(coreIndex());
return QString::fromUtf8(m.name().constData());
} else {
- QMetaProperty p = metaObject->property(coreIndex);
+ QMetaProperty p = metaObject->property(coreIndex());
return QString::fromUtf8(p.name());
}
}
void QQmlPropertyData::markAsOverrideOf(QQmlPropertyData *predecessor)
{
- overrideIndexIsProperty = !predecessor->isFunction();
- overrideIndex = predecessor->coreIndex;
-
- predecessor->flags |= QQmlPropertyData::IsOverridden;
-}
+ setOverrideIndexIsProperty(!predecessor->isFunction());
+ setOverrideIndex(predecessor->coreIndex());
-QStringList QQmlPropertyCache::propertyNames() const
-{
- QStringList keys;
- for (StringCache::ConstIterator iter = stringCache.begin(), cend = stringCache.end(); iter != cend; ++iter)
- keys.append(iter.key());
- return keys;
+ predecessor->_flags.isOverridden = true;
}
struct StaticQtMetaObject : public QObject
@@ -1006,7 +929,6 @@ QString QQmlPropertyCache::signalParameterStringForJS(QV4::ExecutionEngine *engi
{
bool unnamedParameter = false;
const QSet<QString> &illegalNames = engine->v8Engine->illegalNames();
- QString error;
QString parameters;
for (int i = 0; i < parameterNameList.count(); ++i) {
@@ -1169,9 +1091,21 @@ QQmlPropertyCache::property(QJSEngine *engine, QObject *obj,
return qQmlPropertyCacheProperty<const QString &>(engine, obj, name, context, local);
}
+// these two functions are copied from qmetaobject.cpp
static inline const QMetaObjectPrivate *priv(const uint* data)
{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
+static inline const QByteArray stringData(const QMetaObject *mo, int index)
+{
+ Q_ASSERT(priv(mo->d.data)->revision >= 7);
+ const QByteArrayDataPtr data = { const_cast<QByteArrayData*>(&mo->d.stringdata[index]) };
+ Q_ASSERT(data.ptr->ref.isStatic());
+ Q_ASSERT(data.ptr->alloc == 0);
+ Q_ASSERT(data.ptr->capacityReserved == 0);
+ Q_ASSERT(data.ptr->size >= 0);
+ return data;
+}
+
bool QQmlPropertyCache::isDynamicMetaObject(const QMetaObject *mo)
{
return priv(mo->d.data)->revision >= 3 && priv(mo->d.data)->flags & DynamicMetaObject;
@@ -1189,7 +1123,7 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
{
struct Sort { static bool lt(const QPair<QString, QQmlPropertyData *> &lhs,
const QPair<QString, QQmlPropertyData *> &rhs) {
- return lhs.second->coreIndex < rhs.second->coreIndex;
+ return lhs.second->coreIndex() < rhs.second->coreIndex();
} };
struct Insert { static void in(QQmlPropertyCache *This,
@@ -1200,7 +1134,7 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
return;
if (data->isFunction()) {
- if (data->coreIndex < This->methodIndexCacheStart)
+ if (data->coreIndex() < This->methodIndexCacheStart)
return;
QPair<QString, QQmlPropertyData *> entry = qMakePair((QString)iter.key(), data);
@@ -1210,7 +1144,7 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
data = This->overrideData(data);
if (data && !data->isFunction()) Insert::in(This, properties, methods, iter, data);
} else {
- if (data->coreIndex < This->propertyIndexCacheStart)
+ if (data->coreIndex() < This->propertyIndexCacheStart)
return;
QPair<QString, QQmlPropertyData *> entry = qMakePair((QString)iter.key(), data);
@@ -1241,11 +1175,11 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
QQmlPropertyData *data = properties.at(ii).second;
int notifierId = -1;
- if (data->notifyIndex != -1)
- notifierId = data->notifyIndex - signalHandlerIndexCacheStart;
+ if (data->notifyIndex() != -1)
+ notifierId = data->notifyIndex() - signalHandlerIndexCacheStart;
QMetaPropertyBuilder property = builder.addProperty(properties.at(ii).first.toUtf8(),
- QMetaType::typeName(data->propType),
+ QMetaType::typeName(data->propType()),
notifierId);
property.setReadable(true);
@@ -1257,14 +1191,16 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
QQmlPropertyData *data = methods.at(ii).second;
QByteArray returnType;
- if (data->propType != 0)
- returnType = QMetaType::typeName(data->propType);
+ if (data->propType() != 0)
+ returnType = QMetaType::typeName(data->propType());
- QByteArray signature = methods.at(ii).first.toUtf8() + '(';
+ QByteArray signature;
+ // '+=' reserves extra capacity. Follow-up appending will be probably free.
+ signature += methods.at(ii).first.toUtf8() + '(';
QQmlPropertyCacheMethodArguments *arguments = 0;
if (data->hasArguments()) {
- arguments = (QQmlPropertyCacheMethodArguments *)data->arguments;
+ arguments = (QQmlPropertyCacheMethodArguments *)data->arguments();
Q_ASSERT(arguments->argumentsValid);
for (int ii = 0; ii < arguments->arguments[0]; ++ii) {
if (ii != 0) signature.append(',');
@@ -1291,13 +1227,221 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
if (!_defaultPropertyName.isEmpty()) {
QQmlPropertyData *dp = property(_defaultPropertyName, 0, 0);
- if (dp && dp->coreIndex >= propertyIndexCacheStart) {
+ if (dp && dp->coreIndex() >= propertyIndexCacheStart) {
Q_ASSERT(!dp->isFunction());
builder.addClassInfo("DefaultProperty", _defaultPropertyName.toUtf8());
}
}
}
+namespace {
+template <typename StringVisitor, typename TypeInfoVisitor>
+int visitMethods(const QMetaObject &mo, int methodOffset, int methodCount,
+ StringVisitor visitString, TypeInfoVisitor visitTypeInfo)
+{
+ const int intsPerMethod = 5;
+
+ int fieldsForParameterData = 0;
+
+ bool hasRevisionedMethods = false;
+
+ for (int i = 0; i < methodCount; ++i) {
+ const int handle = methodOffset + i * intsPerMethod;
+
+ const uint flags = mo.d.data[handle + 4];
+ if (flags & MethodRevisioned)
+ hasRevisionedMethods = true;
+
+ visitString(mo.d.data[handle + 0]); // name
+ visitString(mo.d.data[handle + 3]); // tag
+
+ const int argc = mo.d.data[handle + 1];
+ const int paramIndex = mo.d.data[handle + 2];
+
+ fieldsForParameterData += argc * 2; // type and name
+ fieldsForParameterData += 1; // + return type
+
+ // return type + args
+ for (int i = 0; i < 1 + argc; ++i) {
+ // type name (maybe)
+ visitTypeInfo(mo.d.data[paramIndex + i]);
+
+ // parameter name
+ if (i > 0)
+ visitString(mo.d.data[paramIndex + argc + i]);
+ }
+ }
+
+ int fieldsForRevisions = 0;
+ if (hasRevisionedMethods)
+ fieldsForRevisions = methodCount;
+
+ return methodCount * intsPerMethod + fieldsForRevisions + fieldsForParameterData;
+}
+
+template <typename StringVisitor, typename TypeInfoVisitor>
+int visitProperties(const QMetaObject &mo, StringVisitor visitString, TypeInfoVisitor visitTypeInfo)
+{
+ const QMetaObjectPrivate *const priv = reinterpret_cast<const QMetaObjectPrivate*>(mo.d.data);
+ const int intsPerProperty = 3;
+
+ bool hasRevisionedProperties = false;
+ bool hasNotifySignals = false;
+
+ for (int i = 0; i < priv->propertyCount; ++i) {
+ const int handle = priv->propertyData + i * intsPerProperty;
+
+ const auto flags = mo.d.data[handle + 2];
+ if (flags & Revisioned) {
+ hasRevisionedProperties = true;
+ }
+ if (flags & Notify)
+ hasNotifySignals = true;
+
+ visitString(mo.d.data[handle]); // name
+ visitTypeInfo(mo.d.data[handle + 1]);
+ }
+
+ int fieldsForPropertyRevisions = 0;
+ if (hasRevisionedProperties)
+ fieldsForPropertyRevisions = priv->propertyCount;
+
+ int fieldsForNotifySignals = 0;
+ if (hasNotifySignals)
+ fieldsForNotifySignals = priv->propertyCount;
+
+ return priv->propertyCount * intsPerProperty + fieldsForPropertyRevisions
+ + fieldsForNotifySignals;
+}
+
+template <typename StringVisitor>
+int visitClassInfo(const QMetaObject &mo, StringVisitor visitString)
+{
+ const QMetaObjectPrivate *const priv = reinterpret_cast<const QMetaObjectPrivate*>(mo.d.data);
+ const int intsPerClassInfo = 2;
+
+ for (int i = 0; i < priv->classInfoCount; ++i) {
+ const int handle = priv->classInfoData + i * intsPerClassInfo;
+
+ visitString(mo.d.data[handle]); // key
+ visitString(mo.d.data[handle + 1]); // value
+ }
+
+ return priv->classInfoCount * intsPerClassInfo;
+}
+
+template <typename StringVisitor>
+int visitEnumerations(const QMetaObject &mo, StringVisitor visitString)
+{
+ const QMetaObjectPrivate *const priv = reinterpret_cast<const QMetaObjectPrivate*>(mo.d.data);
+ const int intsPerEnumerator = 4;
+
+ int fieldCount = priv->enumeratorCount * intsPerEnumerator;
+
+ for (int i = 0; i < priv->enumeratorCount; ++i) {
+ const uint *enumeratorData = mo.d.data + priv->enumeratorData + i * intsPerEnumerator;
+
+ const uint keyCount = enumeratorData[2];
+ fieldCount += keyCount * 2;
+
+ visitString(enumeratorData[0]); // name
+
+ const uint keyOffset = enumeratorData[3];
+
+ for (uint j = 0; j < keyCount; ++j) {
+ visitString(mo.d.data[keyOffset + 2 * j]);
+ }
+ }
+
+ return fieldCount;
+}
+
+template <typename StringVisitor>
+int countMetaObjectFields(const QMetaObject &mo, StringVisitor stringVisitor)
+{
+ const QMetaObjectPrivate *const priv = reinterpret_cast<const QMetaObjectPrivate*>(mo.d.data);
+
+ const auto typeInfoVisitor = [&stringVisitor](uint typeInfo) {
+ if (typeInfo & IsUnresolvedType)
+ stringVisitor(typeInfo & TypeNameIndexMask);
+ };
+
+ int fieldCount = MetaObjectPrivateFieldCount;
+
+ fieldCount += visitMethods(mo, priv->methodData, priv->methodCount, stringVisitor,
+ typeInfoVisitor);
+ fieldCount += visitMethods(mo, priv->constructorData, priv->constructorCount, stringVisitor,
+ typeInfoVisitor);
+
+ fieldCount += visitProperties(mo, stringVisitor, typeInfoVisitor);
+ fieldCount += visitClassInfo(mo, stringVisitor);
+ fieldCount += visitEnumerations(mo, stringVisitor);
+
+ return fieldCount;
+}
+
+} // anonymous namespace
+
+bool QQmlPropertyCache::determineMetaObjectSizes(const QMetaObject &mo, int *fieldCount,
+ int *stringCount)
+{
+ const QMetaObjectPrivate *priv = reinterpret_cast<const QMetaObjectPrivate*>(mo.d.data);
+ if (priv->revision != 7) {
+ return false;
+ }
+
+ uint highestStringIndex = 0;
+ const auto stringIndexVisitor = [&highestStringIndex](uint index) {
+ highestStringIndex = qMax(highestStringIndex, index);
+ };
+
+ *fieldCount = countMetaObjectFields(mo, stringIndexVisitor);
+ *stringCount = highestStringIndex + 1;
+
+ return true;
+}
+
+bool QQmlPropertyCache::addToHash(QCryptographicHash &hash, const QMetaObject &mo)
+{
+ int fieldCount = 0;
+ int stringCount = 0;
+ if (!determineMetaObjectSizes(mo, &fieldCount, &stringCount)) {
+ return false;
+ }
+
+ hash.addData(reinterpret_cast<const char *>(mo.d.data), fieldCount * sizeof(uint));
+ for (int i = 0; i < stringCount; ++i) {
+ hash.addData(stringData(&mo, i));
+ }
+
+ return true;
+}
+
+QByteArray QQmlPropertyCache::checksum(bool *ok)
+{
+ if (!_checksum.isEmpty()) {
+ *ok = true;
+ return _checksum;
+ }
+
+ QCryptographicHash hash(QCryptographicHash::Md5);
+
+ if (_parent) {
+ hash.addData(_parent->checksum(ok));
+ if (!*ok)
+ return QByteArray();
+ }
+
+ if (!addToHash(hash, *createMetaObject())) {
+ *ok = false;
+ return QByteArray();
+ }
+
+ _checksum = hash.result();
+ *ok = !_checksum.isEmpty();
+ return _checksum;
+}
+
/*! \internal
\a index MUST be in the signal index range (see QObjectPrivate::signalIndex()).
This is different from QMetaMethod::methodIndex().
@@ -1306,7 +1450,7 @@ QList<QByteArray> QQmlPropertyCache::signalParameterNames(int index) const
{
QQmlPropertyData *signalData = signal(index);
if (signalData && signalData->hasArguments()) {
- QQmlPropertyCacheMethodArguments *args = (QQmlPropertyCacheMethodArguments *)signalData->arguments;
+ QQmlPropertyCacheMethodArguments *args = (QQmlPropertyCacheMethodArguments *)signalData->arguments();
if (args && args->names)
return *args->names;
const QMetaMethod &method = QMetaObjectPrivate::signal(firstCppMetaObject(), index);
@@ -1408,9 +1552,9 @@ QQmlPropertyCache *QQmlMetaObject::propertyCache(QQmlEnginePrivate *e) const
int QQmlMetaObject::methodReturnType(const QQmlPropertyData &data, QByteArray *unknownTypeError) const
{
- Q_ASSERT(!_m.isNull() && data.coreIndex >= 0);
+ Q_ASSERT(!_m.isNull() && data.coreIndex() >= 0);
- int type = data.propType;
+ int type = data.propType();
const char *propTypeName = 0;
@@ -1420,16 +1564,16 @@ int QQmlMetaObject::methodReturnType(const QQmlPropertyData &data, QByteArray *u
if (_m.isT1()) {
QQmlPropertyCache *c = _m.asT1();
- Q_ASSERT(data.coreIndex < c->methodIndexCacheStart + c->methodIndexCache.count());
+ Q_ASSERT(data.coreIndex() < c->methodIndexCacheStart + c->methodIndexCache.count());
- while (data.coreIndex < c->methodIndexCacheStart)
+ while (data.coreIndex() < c->methodIndexCacheStart)
c = c->_parent;
const QMetaObject *metaObject = c->createMetaObject();
Q_ASSERT(metaObject);
- m = metaObject->method(data.coreIndex);
+ m = metaObject->method(data.coreIndex());
} else {
- m = _m.asT2()->method(data.coreIndex);
+ m = _m.asT2()->method(data.coreIndex());
}
type = m.returnType();
@@ -1453,7 +1597,8 @@ int QQmlMetaObject::methodReturnType(const QQmlPropertyData &data, QByteArray *u
return type;
}
-int *QQmlMetaObject::methodParameterTypes(int index, QVarLengthArray<int, 9> &dummy, QByteArray *unknownTypeError) const
+int *QQmlMetaObject::methodParameterTypes(int index, ArgTypeStorage *argStorage,
+ QByteArray *unknownTypeError) const
{
Q_ASSERT(!_m.isNull() && index >= 0);
@@ -1468,19 +1613,19 @@ int *QQmlMetaObject::methodParameterTypes(int index, QVarLengthArray<int, 9> &du
QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&c->methodIndexCache.at(index - c->methodIndexCacheStart));
- if (rv->arguments && static_cast<A *>(rv->arguments)->argumentsValid)
- return static_cast<A *>(rv->arguments)->arguments;
+ if (rv->arguments() && static_cast<A *>(rv->arguments())->argumentsValid)
+ return static_cast<A *>(rv->arguments())->arguments;
const QMetaObject *metaObject = c->createMetaObject();
Q_ASSERT(metaObject);
QMetaMethod m = metaObject->method(index);
int argc = m.parameterCount();
- if (!rv->arguments) {
+ if (!rv->arguments()) {
A *args = c->createArgumentsObject(argc, m.parameterNames());
- rv->arguments = args;
+ rv->setArguments(args);
}
- A *args = static_cast<A *>(rv->arguments);
+ A *args = static_cast<A *>(rv->arguments());
QList<QByteArray> argTypeNames; // Only loaded if needed
@@ -1504,43 +1649,57 @@ int *QQmlMetaObject::methodParameterTypes(int index, QVarLengthArray<int, 9> &du
args->arguments[ii + 1] = type;
}
args->argumentsValid = true;
- return static_cast<A *>(rv->arguments)->arguments;
+ return static_cast<A *>(rv->arguments())->arguments;
} else {
QMetaMethod m = _m.asT2()->method(index);
- int argc = m.parameterCount();
- dummy.resize(argc + 1);
- dummy[0] = argc;
- QList<QByteArray> argTypeNames; // Only loaded if needed
+ return methodParameterTypes(m, argStorage, unknownTypeError);
- for (int ii = 0; ii < argc; ++ii) {
- int type = m.parameterType(ii);
- QMetaType::TypeFlags flags = QMetaType::typeFlags(type);
- if (flags & QMetaType::IsEnumeration)
- type = QVariant::Int;
- else if (type == QMetaType::UnknownType ||
- (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) &&
- type != qMetaTypeId<QJSValue>())) {
- //the UserType clause is to catch registered QFlags)
- if (argTypeNames.isEmpty())
- argTypeNames = m.parameterTypes();
- type = EnumType(_m.asT2(), argTypeNames.at(ii), type);
- }
- if (type == QMetaType::UnknownType) {
- if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii);
- return 0;
- }
- dummy[ii + 1] = type;
- }
+ }
+}
- return dummy.data();
+int *QQmlMetaObject::methodParameterTypes(const QMetaMethod &m, ArgTypeStorage *argStorage,
+ QByteArray *unknownTypeError) const
+{
+ Q_ASSERT(argStorage);
+
+ int argc = m.parameterCount();
+ argStorage->resize(argc + 1);
+ argStorage->operator[](0) = argc;
+ QList<QByteArray> argTypeNames; // Only loaded if needed
+
+ for (int ii = 0; ii < argc; ++ii) {
+ int type = m.parameterType(ii);
+ QMetaType::TypeFlags flags = QMetaType::typeFlags(type);
+ if (flags & QMetaType::IsEnumeration)
+ type = QVariant::Int;
+ else if (type == QMetaType::UnknownType ||
+ (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) &&
+ type != qMetaTypeId<QJSValue>())) {
+ //the UserType clause is to catch registered QFlags)
+ if (argTypeNames.isEmpty())
+ argTypeNames = m.parameterTypes();
+ type = EnumType(_m.asT2(), argTypeNames.at(ii), type);
+ }
+ if (type == QMetaType::UnknownType) {
+ if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii);
+ return 0;
+ }
+ argStorage->operator[](ii + 1) = type;
}
+
+ return argStorage->data();
}
void QQmlObjectOrGadget::metacall(QMetaObject::Call type, int index, void **argv) const
{
- if (ptr.isT1())
+ if (ptr.isNull()) {
+ const QMetaObject *metaObject = _m.asT2();
+ metaObject->d.static_metacall(0, type, index, argv);
+ }
+ else if (ptr.isT1()) {
QMetaObject::metacall(ptr.asT1(), type, index, argv);
+ }
else {
const QMetaObject *metaObject = _m.asT1()->metaObject();
QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, &metaObject, &index);
@@ -1548,4 +1707,11 @@ void QQmlObjectOrGadget::metacall(QMetaObject::Call type, int index, void **argv
}
}
+int *QQmlStaticMetaObject::constructorParameterTypes(int index, ArgTypeStorage *dummy,
+ QByteArray *unknownTypeError) const
+{
+ QMetaMethod m = _m.asT2()->constructor(index);
+ return methodParameterTypes(m, dummy, unknownTypeError);
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index b2171dd86b..c27ea796e0 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -55,6 +55,7 @@
#include <private/qflagpointer_p.h>
#include "qqmlcleanup_p.h"
#include "qqmlnotifier_p.h"
+#include <private/qqmlpropertyindex_p.h>
#include <private/qhashedstring_p.h>
#include <QtCore/qvarlengtharray.h>
@@ -62,17 +63,20 @@
#include <private/qv4value_p.h>
+#include <limits>
+
QT_BEGIN_NAMESPACE
+class QCryptographicHash;
class QMetaProperty;
class QQmlEngine;
class QJSEngine;
class QQmlPropertyData;
-class QQmlAccessors;
class QMetaObjectBuilder;
class QQmlPropertyCacheMethodArguments;
class QQmlVMEMetaObject;
-class QQmlPropertyCacheCreator;
+template <typename T> class QQmlPropertyCacheCreator;
+template <typename T> class QQmlPropertyCacheAliasCreator;
// We have this somewhat awful split between RawData and Data so that RawData can be
// used in unions. In normal code, you should always use Data which initializes RawData
@@ -80,151 +84,205 @@ class QQmlPropertyCacheCreator;
class QQmlPropertyRawData
{
public:
- enum Flag {
- NoFlags = 0x00000000,
- ValueTypeFlagMask = 0x0000FFFF, // Flags in valueTypeFlags must fit in this mask
+ typedef QObjectPrivate::StaticMetaCallFunction StaticMetaCallFunction;
+
+ struct Flags {
+ enum Types {
+ OtherType = 0,
+ FunctionType = 1, // Is an invokable
+ QObjectDerivedType = 2, // Property type is a QObject* derived type
+ EnumType = 3, // Property type is an enum
+ QListType = 4, // Property type is a QML list
+ QmlBindingType = 5, // Property type is a QQmlBinding*
+ QJSValueType = 6, // Property type is a QScriptValue
+ V4HandleType = 7, // Property type is a QQmlV4Handle
+ VarPropertyType = 8, // Property type is a "var" property of VMEMO
+ QVariantType = 9 // Property is a QVariant
+ };
+
+ // The _otherBits (which "pad" the Flags struct to align it nicely) are used
+ // to store the relative property index. It will only get used when said index fits. See
+ // trySetStaticMetaCallFunction for details.
+ // (Note: this padding is done here, because certain compilers have surprising behavior
+ // when an enum is declared in-between two bit fields.)
+ enum { BitsLeftInFlags = 10 };
+ unsigned _otherBits : BitsLeftInFlags; // align to 32 bits
// Can apply to all properties, except IsFunction
- IsConstant = 0x00000001, // Has CONST flag
- IsWritable = 0x00000002, // Has WRITE function
- IsResettable = 0x00000004, // Has RESET function
- IsAlias = 0x00000008, // Is a QML alias to another property
- IsFinal = 0x00000010, // Has FINAL flag
- IsOverridden = 0x00000020, // Is overridden by a extension property
- IsDirect = 0x00000040, // Exists on a C++ QMetaObject
- HasAccessors = 0x00000080, // Has property accessors
-
- // These are mutualy exclusive
- IsFunction = 0x00000100, // Is an invokable
- IsQObjectDerived = 0x00000200, // Property type is a QObject* derived type
- IsEnumType = 0x00000400, // Property type is an enum
- IsQList = 0x00000800, // Property type is a QML list
- IsQmlBinding = 0x00001000, // Property type is a QQmlBinding*
- IsQJSValue = 0x00002000, // Property type is a QScriptValue
- IsV4Handle = 0x00004000, // Property type is a QQmlV4Handle
- IsVarProperty = 0x00008000, // Property type is a "var" property of VMEMO
- IsValueTypeVirtual = 0x00010000, // Property is a value type "virtual" property
- IsQVariant = 0x00020000, // Property is a QVariant
+ unsigned isConstant : 1; // Has CONST flag
+ unsigned isWritable : 1; // Has WRITE function
+ unsigned isResettable : 1; // Has RESET function
+ unsigned isAlias : 1; // Is a QML alias to another property
+ unsigned isFinal : 1; // Has FINAL flag
+ unsigned isOverridden : 1; // Is overridden by a extension property
+ unsigned isDirect : 1; // Exists on a C++ QMetaObject
+
+ unsigned type : 4; // stores an entry of Types
// Apply only to IsFunctions
- IsVMEFunction = 0x00040000, // Function was added by QML
- HasArguments = 0x00080000, // Function takes arguments
- IsSignal = 0x00100000, // Function is a signal
- IsVMESignal = 0x00200000, // Signal was added by QML
- IsV4Function = 0x00400000, // Function takes QQmlV4Function* args
- IsSignalHandler = 0x00800000, // Function is a signal handler
- IsOverload = 0x01000000, // Function is an overload of another function
- IsCloned = 0x02000000, // The function was marked as cloned
+ unsigned isVMEFunction : 1; // Function was added by QML
+ unsigned hasArguments : 1; // Function takes arguments
+ unsigned isSignal : 1; // Function is a signal
+ unsigned isVMESignal : 1; // Signal was added by QML
+ unsigned isV4Function : 1; // Function takes QQmlV4Function* args
+ unsigned isSignalHandler : 1; // Function is a signal handler
+ unsigned isOverload : 1; // Function is an overload of another function
+ unsigned isCloned : 1; // The function was marked as cloned
+ unsigned isConstructor : 1; // The function was marked is a constructor
// Internal QQmlPropertyCache flags
- NotFullyResolved = 0x04000000, // True if the type data is to be lazily resolved
+ unsigned notFullyResolved : 1; // True if the type data is to be lazily resolved
+ unsigned overrideIndexIsProperty: 1;
- // Flags that are set based on the propType field
- PropTypeFlagMask = IsQObjectDerived | IsEnumType | IsQList | IsQmlBinding | IsQJSValue |
- IsV4Handle | IsQVariant,
+ inline Flags();
+ inline bool operator==(const Flags &other) const;
+ inline void copyPropertyTypeFlags(Flags from);
};
- Q_DECLARE_FLAGS(Flags, Flag)
-
- Flags getFlags() const { return Flag(flags); }
- void setFlags(Flags f) { flags = f; }
-
- bool isValid() const { return coreIndex != -1; }
-
- bool isConstant() const { return flags & IsConstant; }
- bool isWritable() const { return flags & IsWritable; }
- bool isResettable() const { return flags & IsResettable; }
- bool isAlias() const { return flags & IsAlias; }
- bool isFinal() const { return flags & IsFinal; }
- bool isOverridden() const { return flags & IsOverridden; }
- bool isDirect() const { return flags & IsDirect; }
- bool hasAccessors() const { return flags & HasAccessors; }
- bool isFunction() const { return flags & IsFunction; }
- bool isQObject() const { return flags & IsQObjectDerived; }
- bool isEnum() const { return flags & IsEnumType; }
- bool isQList() const { return flags & IsQList; }
- bool isQmlBinding() const { return flags & IsQmlBinding; }
- bool isQJSValue() const { return flags & IsQJSValue; }
- bool isV4Handle() const { return flags & IsV4Handle; }
- bool isVarProperty() const { return flags & IsVarProperty; }
- bool isValueTypeVirtual() const { return flags & IsValueTypeVirtual; }
- bool isQVariant() const { return flags & IsQVariant; }
- bool isVMEFunction() const { return flags & IsVMEFunction; }
- bool hasArguments() const { return flags & HasArguments; }
- bool isSignal() const { return flags & IsSignal; }
- bool isVMESignal() const { return flags & IsVMESignal; }
- bool isV4Function() const { return flags & IsV4Function; }
- bool isSignalHandler() const { return flags & IsSignalHandler; }
- bool isOverload() const { return flags & IsOverload; }
- bool isCloned() const { return flags & IsCloned; }
-
- bool hasOverride() const { return !(flags & IsValueTypeVirtual) &&
- !(flags & HasAccessors) &&
- overrideIndex >= 0; }
- bool hasRevision() const { return !(flags & HasAccessors) && revision != 0; }
-
- bool isFullyResolved() const { return !(flags & NotFullyResolved); }
-
- // Returns -1 if not a value type virtual property
- inline int getValueTypeCoreIndex() const;
-
- // Returns the "encoded" index for use with bindings. Encoding is:
- // coreIndex | ((valueTypeCoreIndex + 1) << 16)
- inline int encodedIndex() const;
- static int encodeValueTypePropertyIndex(int coreIndex, int valueTypeCoreIndex)
- { return coreIndex | ((valueTypeCoreIndex + 1) << 16); }
- static int decodeValueTypePropertyIndex(int index, int *coreIndex = 0) {
- if (coreIndex) *coreIndex = index & 0xffff;
- return (index >> 16) - 1;
+
+ Flags flags() const { return _flags; }
+ void setFlags(Flags f)
+ {
+ unsigned otherBits = _flags._otherBits;
+ _flags = f;
+ _flags._otherBits = otherBits;
}
- union {
- int propType; // When !NotFullyResolved
- const char *propTypeName; // When NotFullyResolved
- };
- union {
- // The notify index is in the range returned by QObjectPrivate::signalIndex().
- // This is different from QMetaMethod::methodIndex().
- int notifyIndex; // When !IsFunction
- void *arguments; // When IsFunction && HasArguments
- };
+ bool isValid() const { return coreIndex() != -1; }
+
+ bool isConstant() const { return _flags.isConstant; }
+ bool isWritable() const { return _flags.isWritable; }
+ void setWritable(bool onoff) { _flags.isWritable = onoff; }
+ bool isResettable() const { return _flags.isResettable; }
+ bool isAlias() const { return _flags.isAlias; }
+ bool isFinal() const { return _flags.isFinal; }
+ bool isOverridden() const { return _flags.isOverridden; }
+ bool isDirect() const { return _flags.isDirect; }
+ bool hasStaticMetaCallFunction() const { return staticMetaCallFunction() != nullptr; }
+ bool isFunction() const { return _flags.type == Flags::FunctionType; }
+ bool isQObject() const { return _flags.type == Flags::QObjectDerivedType; }
+ bool isEnum() const { return _flags.type == Flags::EnumType; }
+ bool isQList() const { return _flags.type == Flags::QListType; }
+ bool isQmlBinding() const { return _flags.type == Flags::QmlBindingType; }
+ bool isQJSValue() const { return _flags.type == Flags::QJSValueType; }
+ bool isV4Handle() const { return _flags.type == Flags::V4HandleType; }
+ bool isVarProperty() const { return _flags.type == Flags::VarPropertyType; }
+ bool isQVariant() const { return _flags.type == Flags::QVariantType; }
+ bool isVMEFunction() const { return _flags.isVMEFunction; }
+ bool hasArguments() const { return _flags.hasArguments; }
+ bool isSignal() const { return _flags.isSignal; }
+ bool isVMESignal() const { return _flags.isVMESignal; }
+ bool isV4Function() const { return _flags.isV4Function; }
+ bool isSignalHandler() const { return _flags.isSignalHandler; }
+ bool isOverload() const { return _flags.isOverload; }
+ void setOverload(bool onoff) { _flags.isOverload = onoff; }
+ bool isCloned() const { return _flags.isCloned; }
+ bool isConstructor() const { return _flags.isConstructor; }
+
+ bool hasOverride() const { return overrideIndex() >= 0; }
+ bool hasRevision() const { return revision() != 0; }
+
+ bool isFullyResolved() const { return !_flags.notFullyResolved; }
+
+ int propType() const { Q_ASSERT(isFullyResolved()); return _propType; }
+ void setPropType(int pt)
+ {
+ Q_ASSERT(pt >= 0);
+ Q_ASSERT(pt <= std::numeric_limits<qint16>::max());
+ _propType = quint16(pt);
+ }
- union {
- struct { // When !HasAccessors
- qint16 revision;
- qint16 metaObjectOffset;
-
- union {
- struct { // When IsValueTypeVirtual
- quint16 valueTypeFlags; // flags of the access property on the value type proxy
- // object
- quint16 valueTypePropType; // The QVariant::Type of access property on the value
- // type proxy object
- quint16 valueTypeCoreIndex; // The prop index of the access property on the value
- // type proxy object
- };
-
- struct { // When !IsValueTypeVirtual
- uint overrideIndexIsProperty : 1;
- signed int overrideIndex : 31;
- };
- };
- };
- struct { // When HasAccessors
- QQmlAccessors *accessors;
- };
- };
- int coreIndex;
+ int notifyIndex() const { return _notifyIndex; }
+ void setNotifyIndex(int idx)
+ {
+ Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
+ Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
+ _notifyIndex = qint16(idx);
+ }
+
+ bool overrideIndexIsProperty() const { return _flags.overrideIndexIsProperty; }
+ void setOverrideIndexIsProperty(bool onoff) { _flags.overrideIndexIsProperty = onoff; }
+
+ int overrideIndex() const { return _overrideIndex; }
+ void setOverrideIndex(int idx)
+ {
+ Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
+ Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
+ _overrideIndex = qint16(idx);
+ }
+
+ int coreIndex() const { return _coreIndex; }
+ void setCoreIndex(int idx)
+ {
+ Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
+ Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
+ _coreIndex = qint16(idx);
+ }
+
+ int revision() const { return _revision; }
+ void setRevision(int rev)
+ {
+ Q_ASSERT(rev >= std::numeric_limits<qint16>::min());
+ Q_ASSERT(rev <= std::numeric_limits<qint16>::max());
+ _revision = qint16(rev);
+ }
+
+ QQmlPropertyCacheMethodArguments *arguments() const { return _arguments; }
+ void setArguments(QQmlPropertyCacheMethodArguments *args) { _arguments = args; }
+
+ int metaObjectOffset() const { return _metaObjectOffset; }
+ void setMetaObjectOffset(int off)
+ {
+ Q_ASSERT(off >= std::numeric_limits<qint16>::min());
+ Q_ASSERT(off <= std::numeric_limits<qint16>::max());
+ _metaObjectOffset = qint16(off);
+ }
+
+ StaticMetaCallFunction staticMetaCallFunction() const { return _staticMetaCallFunction; }
+ void trySetStaticMetaCallFunction(StaticMetaCallFunction f, unsigned relativePropertyIndex)
+ {
+ if (relativePropertyIndex < (1 << Flags::BitsLeftInFlags) - 1) {
+ _flags._otherBits = relativePropertyIndex;
+ _staticMetaCallFunction = f;
+ }
+ }
+ quint16 relativePropertyIndex() const { Q_ASSERT(hasStaticMetaCallFunction()); return _flags._otherBits; }
private:
+ Flags _flags;
+ qint16 _coreIndex;
+ quint16 _propType;
+
+ // The notify index is in the range returned by QObjectPrivate::signalIndex().
+ // This is different from QMetaMethod::methodIndex().
+ qint16 _notifyIndex;
+ qint16 _overrideIndex;
+
+ qint16 _revision;
+ qint16 _metaObjectOffset;
+
+ QQmlPropertyCacheMethodArguments *_arguments;
+ StaticMetaCallFunction _staticMetaCallFunction;
+
friend class QQmlPropertyData;
friend class QQmlPropertyCache;
- quint32 flags;
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyRawData::Flags)
+
+#if QT_POINTER_SIZE == 4
+Q_STATIC_ASSERT(sizeof(QQmlPropertyRawData) == 24);
+#else // QT_POINTER_SIZE == 8
+Q_STATIC_ASSERT(sizeof(QQmlPropertyRawData) == 32);
+#endif
class QQmlPropertyData : public QQmlPropertyRawData
{
public:
+ enum WriteFlag {
+ BypassInterceptor = 0x01,
+ DontRemoveBinding = 0x02,
+ RemoveBindingOnAliasWrite = 0x04
+ };
+ Q_DECLARE_FLAGS(WriteFlags, WriteFlag)
+
inline QQmlPropertyData();
inline QQmlPropertyData(const QQmlPropertyRawData &);
@@ -238,11 +296,57 @@ public:
void markAsOverrideOf(QQmlPropertyData *predecessor);
+ inline void readProperty(QObject *target, void *property) const
+ {
+ void *args[] = { property, 0 };
+ readPropertyWithArgs(target, args);
+ }
+
+ inline void readPropertyWithArgs(QObject *target, void *args[]) const
+ {
+ if (hasStaticMetaCallFunction())
+ staticMetaCallFunction()(target, QMetaObject::ReadProperty, relativePropertyIndex(), args);
+ else if (isDirect())
+ target->qt_metacall(QMetaObject::ReadProperty, coreIndex(), args);
+ else
+ QMetaObject::metacall(target, QMetaObject::ReadProperty, coreIndex(), args);
+ }
+
+ bool writeProperty(QObject *target, void *value, WriteFlags flags) const
+ {
+ int status = -1;
+ void *argv[] = { value, 0, &status, &flags };
+ if (flags.testFlag(BypassInterceptor) && hasStaticMetaCallFunction())
+ staticMetaCallFunction()(target, QMetaObject::WriteProperty, relativePropertyIndex(), argv);
+ else if (flags.testFlag(BypassInterceptor) && isDirect())
+ target->qt_metacall(QMetaObject::WriteProperty, coreIndex(), argv);
+ else
+ QMetaObject::metacall(target, QMetaObject::WriteProperty, coreIndex(), argv);
+ return true;
+ }
+
+ static Flags defaultSignalFlags()
+ {
+ Flags f;
+ f.isSignal = true;
+ f.type = Flags::FunctionType;
+ f.isVMESignal = true;
+ return f;
+ }
+
+ static Flags defaultSlotFlags()
+ {
+ Flags f;
+ f.type = Flags::FunctionType;
+ f.isVMEFunction = true;
+ return f;
+ }
+
private:
friend class QQmlPropertyCache;
void lazyLoad(const QMetaProperty &);
void lazyLoad(const QMetaMethod &);
- bool notFullyResolved() const { return flags & NotFullyResolved; }
+ bool notFullyResolved() const { return _flags.notFullyResolved; }
};
class QQmlPropertyCacheMethodArguments;
@@ -261,21 +365,21 @@ public:
QQmlPropertyCache *copy();
QQmlPropertyCache *copyAndAppend(const QMetaObject *,
- QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
- QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
- QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
+ QQmlPropertyRawData::Flags propertyFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyRawData::Flags methodFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags());
QQmlPropertyCache *copyAndAppend(const QMetaObject *, int revision,
- QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
- QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
- QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
+ QQmlPropertyRawData::Flags propertyFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyRawData::Flags methodFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags());
QQmlPropertyCache *copyAndReserve(int propertyCount,
int methodCount, int signalCount);
- void appendProperty(const QString &,
- quint32 flags, int coreIndex, int propType, int notifyIndex);
- void appendSignal(const QString &, quint32, int coreIndex, const int *types = 0,
- const QList<QByteArray> &names = QList<QByteArray>());
- void appendMethod(const QString &, quint32 flags, int coreIndex,
+ void appendProperty(const QString &, QQmlPropertyRawData::Flags flags, int coreIndex,
+ int propType, int notifyIndex);
+ void appendSignal(const QString &, QQmlPropertyRawData::Flags, int coreIndex,
+ const int *types = 0, const QList<QByteArray> &names = QList<QByteArray>());
+ void appendMethod(const QString &, QQmlPropertyData::Flags flags, int coreIndex,
const QList<QByteArray> &names = QList<QByteArray>());
const QMetaObject *metaObject() const;
@@ -292,7 +396,6 @@ public:
QQmlPropertyData *method(int) const;
QQmlPropertyData *signal(int index) const;
int methodIndexToSignalIndex(int) const;
- QStringList propertyNames() const;
QString defaultPropertyName() const;
QQmlPropertyData *defaultProperty() const;
@@ -328,23 +431,29 @@ public:
void toMetaObjectBuilder(QMetaObjectBuilder &);
+ static bool determineMetaObjectSizes(const QMetaObject &mo, int *fieldCount, int *stringCount);
+ static bool addToHash(QCryptographicHash &hash, const QMetaObject &mo);
+
+ QByteArray checksum(bool *ok);
+
protected:
- virtual void destroy();
- virtual void clear();
+ void destroy() override;
+ void clear() override;
private:
friend class QQmlEnginePrivate;
friend class QQmlCompiler;
- friend class QQmlPropertyCacheCreator;
+ template <typename T> friend class QQmlPropertyCacheCreator;
+ template <typename T> friend class QQmlPropertyCacheAliasCreator;
friend class QQmlComponentAndAliasResolver;
friend class QQmlMetaObject;
inline QQmlPropertyCache *copy(int reserve);
void append(const QMetaObject *, int revision,
- QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
- QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
- QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
+ QQmlPropertyRawData::Flags propertyFlags = QQmlPropertyRawData::Flags(),
+ QQmlPropertyRawData::Flags methodFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags());
QQmlPropertyCacheMethodArguments *createArgumentsObject(int count, const QList<QByteArray> &names);
@@ -396,6 +505,7 @@ private:
QByteArray _dynamicStringData;
QString _defaultPropertyName;
QQmlPropertyCacheMethodArguments *argumentsCache;
+ QByteArray _checksum;
};
// QQmlMetaObject serves as a wrapper around either QMetaObject or QQmlPropertyCache.
@@ -408,6 +518,8 @@ class QQmlEnginePrivate;
class Q_QML_EXPORT QQmlMetaObject
{
public:
+ typedef QVarLengthArray<int, 9> ArgTypeStorage;
+
inline QQmlMetaObject();
inline QQmlMetaObject(QObject *);
inline QQmlMetaObject(const QMetaObject *);
@@ -427,7 +539,8 @@ public:
QQmlPropertyCache *propertyCache(QQmlEnginePrivate *) const;
int methodReturnType(const QQmlPropertyData &data, QByteArray *unknownTypeError) const;
- int *methodParameterTypes(int index, QVarLengthArray<int, 9> &dummy, QByteArray *unknownTypeError) const;
+ int *methodParameterTypes(int index, ArgTypeStorage *argStorage,
+ QByteArray *unknownTypeError) const;
static bool canConvert(const QQmlMetaObject &from, const QQmlMetaObject &to);
@@ -437,6 +550,9 @@ public:
protected:
QBiPointer<QQmlPropertyCache, const QMetaObject> _m;
+ int *methodParameterTypes(const QMetaMethod &method, ArgTypeStorage *argStorage,
+ QByteArray *unknownTypeError) const;
+
};
class QQmlObjectOrGadget: public QQmlMetaObject
@@ -455,45 +571,105 @@ public:
private:
QBiPointer<QObject, void> ptr;
+
+protected:
+ QQmlObjectOrGadget(const QMetaObject* metaObject)
+ : QQmlMetaObject(metaObject)
+ {}
+
};
-QQmlPropertyData::QQmlPropertyData()
+class QQmlStaticMetaObject : public QQmlObjectOrGadget {
+public:
+ QQmlStaticMetaObject(const QMetaObject* metaObject)
+ : QQmlObjectOrGadget(metaObject)
+ {}
+ int *constructorParameterTypes(int index, ArgTypeStorage *dummy, QByteArray *unknownTypeError) const;
+};
+
+QQmlPropertyRawData::Flags::Flags()
+ : _otherBits(0)
+ , isConstant(false)
+ , isWritable(false)
+ , isResettable(false)
+ , isAlias(false)
+ , isFinal(false)
+ , isOverridden(false)
+ , isDirect(false)
+ , type(OtherType)
+ , isVMEFunction(false)
+ , hasArguments(false)
+ , isSignal(false)
+ , isVMESignal(false)
+ , isV4Function(false)
+ , isSignalHandler(false)
+ , isOverload(false)
+ , isCloned(false)
+ , isConstructor(false)
+ , notFullyResolved(false)
+ , overrideIndexIsProperty(false)
+{}
+
+bool QQmlPropertyRawData::Flags::operator==(const QQmlPropertyRawData::Flags &other) const
{
- propType = 0;
- coreIndex = -1;
- notifyIndex = -1;
- overrideIndexIsProperty = false;
- overrideIndex = -1;
- revision = 0;
- metaObjectOffset = -1;
- flags = 0;
+ return isConstant == other.isConstant &&
+ isWritable == other.isWritable &&
+ isResettable == other.isResettable &&
+ isAlias == other.isAlias &&
+ isFinal == other.isFinal &&
+ isOverridden == other.isOverridden &&
+ type == other.type &&
+ isVMEFunction == other.isVMEFunction &&
+ hasArguments == other.hasArguments &&
+ isSignal == other.isSignal &&
+ isVMESignal == other.isVMESignal &&
+ isV4Function == other.isV4Function &&
+ isSignalHandler == other.isSignalHandler &&
+ isOverload == other.isOverload &&
+ isCloned == other.isCloned &&
+ isConstructor == other.isConstructor &&
+ notFullyResolved == other.notFullyResolved &&
+ overrideIndexIsProperty == other.overrideIndexIsProperty;
}
-QQmlPropertyData::QQmlPropertyData(const QQmlPropertyRawData &d)
+void QQmlPropertyRawData::Flags::copyPropertyTypeFlags(QQmlPropertyRawData::Flags from)
{
- *(static_cast<QQmlPropertyRawData *>(this)) = d;
+ switch (from.type) {
+ case QObjectDerivedType:
+ case EnumType:
+ case QListType:
+ case QmlBindingType:
+ case QJSValueType:
+ case V4HandleType:
+ case QVariantType:
+ type = from.type;
+ }
}
-bool QQmlPropertyData::operator==(const QQmlPropertyRawData &other)
+QQmlPropertyData::QQmlPropertyData()
{
- return flags == other.flags &&
- propType == other.propType &&
- coreIndex == other.coreIndex &&
- notifyIndex == other.notifyIndex &&
- revision == other.revision &&
- (!isValueTypeVirtual() ||
- (valueTypeCoreIndex == other.valueTypeCoreIndex &&
- valueTypePropType == other.valueTypePropType));
+ setCoreIndex(-1);
+ setPropType(0);
+ setNotifyIndex(-1);
+ setOverrideIndex(-1);
+ setRevision(0);
+ setMetaObjectOffset(-1);
+ setArguments(nullptr);
+ trySetStaticMetaCallFunction(nullptr, 0);
}
-int QQmlPropertyRawData::getValueTypeCoreIndex() const
+QQmlPropertyData::QQmlPropertyData(const QQmlPropertyRawData &d)
{
- return isValueTypeVirtual()?valueTypeCoreIndex:-1;
+ *(static_cast<QQmlPropertyRawData *>(this)) = d;
}
-int QQmlPropertyRawData::encodedIndex() const
+bool QQmlPropertyData::operator==(const QQmlPropertyRawData &other)
{
- return isValueTypeVirtual()?QQmlPropertyData::encodeValueTypePropertyIndex(coreIndex, valueTypeCoreIndex):coreIndex;
+ return flags() == other.flags() &&
+ propType() == other.propType() &&
+ coreIndex() == other.coreIndex() &&
+ notifyIndex() == other.notifyIndex() &&
+ revision() == other.revision();
}
inline QQmlPropertyData *QQmlPropertyCache::ensureResolved(QQmlPropertyData *p) const
@@ -504,6 +680,21 @@ inline QQmlPropertyData *QQmlPropertyCache::ensureResolved(QQmlPropertyData *p)
return p;
}
+// Returns this property cache's metaObject. May be null if it hasn't been created yet.
+inline const QMetaObject *QQmlPropertyCache::metaObject() const
+{
+ return _metaObject;
+}
+
+// Returns the first C++ type's QMetaObject - that is, the first QMetaObject not created by
+// QML
+inline const QMetaObject *QQmlPropertyCache::firstCppMetaObject() const
+{
+ while (_parent && (_metaObject == 0 || _ownMetaObject))
+ return _parent->firstCppMetaObject();
+ return _metaObject;
+}
+
inline QQmlPropertyData *QQmlPropertyCache::property(int index) const
{
if (index < 0 || index >= (propertyIndexCacheStart + propertyIndexCache.count()))
@@ -516,22 +707,73 @@ inline QQmlPropertyData *QQmlPropertyCache::property(int index) const
return ensureResolved(rv);
}
+inline QQmlPropertyData *QQmlPropertyCache::method(int index) const
+{
+ if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.count()))
+ return 0;
+
+ if (index < methodIndexCacheStart)
+ return _parent->method(index);
+
+ QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&methodIndexCache.at(index - methodIndexCacheStart));
+ return ensureResolved(rv);
+}
+
+/*! \internal
+ \a index MUST be in the signal index range (see QObjectPrivate::signalIndex()).
+ This is different from QMetaMethod::methodIndex().
+*/
+inline QQmlPropertyData *QQmlPropertyCache::signal(int index) const
+{
+ if (index < 0 || index >= (signalHandlerIndexCacheStart + signalHandlerIndexCache.count()))
+ return 0;
+
+ if (index < signalHandlerIndexCacheStart)
+ return _parent->signal(index);
+
+ QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&methodIndexCache.at(index - signalHandlerIndexCacheStart));
+ Q_ASSERT(rv->isSignal() || rv->coreIndex() == -1);
+ return ensureResolved(rv);
+}
+
+inline int QQmlPropertyCache::methodIndexToSignalIndex(int index) const
+{
+ if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.count()))
+ return index;
+
+ if (index < methodIndexCacheStart)
+ return _parent->methodIndexToSignalIndex(index);
+
+ return index - methodIndexCacheStart + signalHandlerIndexCacheStart;
+}
+
+// Returns the name of the default property for this cache
+inline QString QQmlPropertyCache::defaultPropertyName() const
+{
+ return _defaultPropertyName;
+}
+
+inline QQmlPropertyCache *QQmlPropertyCache::parent() const
+{
+ return _parent;
+}
+
QQmlPropertyData *
QQmlPropertyCache::overrideData(QQmlPropertyData *data) const
{
if (!data->hasOverride())
return 0;
- if (data->overrideIndexIsProperty)
- return property(data->overrideIndex);
+ if (data->overrideIndexIsProperty())
+ return property(data->overrideIndex());
else
- return method(data->overrideIndex);
+ return method(data->overrideIndex());
}
bool QQmlPropertyCache::isAllowedInRevision(QQmlPropertyData *data) const
{
- return (data->hasAccessors() || (data->metaObjectOffset == -1 && data->revision == 0)) ||
- (allowedRevisionCache[data->metaObjectOffset] >= data->revision);
+ return (data->metaObjectOffset() == -1 && data->revision() == 0) ||
+ (allowedRevisionCache[data->metaObjectOffset()] >= data->revision());
}
int QQmlPropertyCache::propertyCount() const
@@ -637,6 +879,51 @@ const QMetaObject *QQmlMetaObject::metaObject() const
else return _m.asT2();
}
+class QQmlPropertyCacheVector
+{
+public:
+ QQmlPropertyCacheVector() {}
+ QQmlPropertyCacheVector(QQmlPropertyCacheVector &&other)
+ : data(std::move(other.data)) {}
+ QQmlPropertyCacheVector &operator=(QQmlPropertyCacheVector &&other) {
+ QVector<QFlagPointer<QQmlPropertyCache>> moved(std::move(other.data));
+ data.swap(moved);
+ return *this;
+ }
+
+ ~QQmlPropertyCacheVector() { clear(); }
+ void resize(int size) { return data.resize(size); }
+ int count() const { return data.count(); }
+ void clear()
+ {
+ for (int i = 0; i < data.count(); ++i) {
+ if (QQmlPropertyCache *cache = data.at(i).data())
+ cache->release();
+ }
+ data.clear();
+ }
+
+ void append(QQmlPropertyCache *cache) { cache->addref(); data.append(cache); }
+ QQmlPropertyCache *at(int index) const { return data.at(index).data(); }
+ void set(int index, QQmlPropertyCache *replacement) {
+ if (QQmlPropertyCache *oldCache = data.at(index).data()) {
+ if (replacement == oldCache)
+ return;
+ oldCache->release();
+ }
+ data[index] = replacement;
+ replacement->addref();
+ }
+
+ void setNeedsVMEMetaObject(int index) { data[index].setFlag(); }
+ bool needsVMEMetaObject(int index) const { return data.at(index).flag(); }
+private:
+ Q_DISABLE_COPY(QQmlPropertyCacheVector)
+ QVector<QFlagPointer<QQmlPropertyCache>> data;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyData::WriteFlags)
+
QT_END_NAMESPACE
#endif // QQMLPROPERTYCACHE_P_H
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlpropertyindex_p.h
index 2c9e04d5e0..ebc1828efb 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlpropertyindex_p.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QQMLCOMPILER_P_H
-#define QQMLCOMPILER_P_H
+#ifndef QQMLPROPERTYINDEX_P_H
+#define QQMLPROPERTYINDEX_P_H
//
// W A R N I N G
@@ -51,89 +51,83 @@
// We mean it.
//
-#include "qqml.h"
-#include "qqmlerror.h"
-#include "qqmlengine_p.h"
-#include <private/qbitfield_p.h>
-#include "qqmlpropertycache_p.h"
-#include "qqmltypenamecache_p.h"
-#include "qqmltypeloader_p.h"
-#include "private/qv4identifier_p.h"
-#include <private/qqmljsastfwd_p.h>
-#include "qqmlcustomparser_p.h"
-
-#include <QtCore/qbytearray.h>
-#include <QtCore/qset.h>
-#include <QtCore/QCoreApplication>
+#include <private/qglobal_p.h>
QT_BEGIN_NAMESPACE
-namespace QV4 {
-namespace CompiledData {
-struct CompilationUnit;
-struct Unit;
-}
-}
-
-class QQmlEngine;
-class QQmlComponent;
-class QQmlContext;
-class QQmlContextData;
-
-// ### Merge with QV4::CompiledData::CompilationUnit
-class Q_AUTOTEST_EXPORT QQmlCompiledData : public QQmlRefCount, public QQmlCleanup
+class QQmlPropertyIndex
{
+ qint32 index;
+
public:
- QQmlCompiledData(QQmlEngine *engine);
- virtual ~QQmlCompiledData();
+ QQmlPropertyIndex()
+ { index = -1; }
- QQmlEngine *engine;
+ static QQmlPropertyIndex fromEncoded(qint32 encodedIndex)
+ {
+ QQmlPropertyIndex idx;
+ idx.index = encodedIndex;
+ return idx;
+ }
- int metaTypeId;
- int listMetaTypeId;
- bool isRegisteredWithEngine;
+ explicit QQmlPropertyIndex(int coreIndex)
+ { index = encode(coreIndex, -1); }
- struct TypeReference
- {
- TypeReference()
- : type(0), typePropertyCache(0), component(0)
- , majorVersion(0)
- , minorVersion(0)
- , isFullyDynamicType(false)
- {}
+ explicit QQmlPropertyIndex(int coreIndex, int valueTypeIndex)
+ : index(encode(coreIndex, valueTypeIndex))
+ {}
- QQmlType *type;
- QQmlPropertyCache *typePropertyCache;
- QQmlCompiledData *component;
+ bool isValid() const
+ { return index != -1; }
- int majorVersion;
- int minorVersion;
- // Types such as QQmlPropertyMap can add properties dynamically at run-time and
- // therefore cannot have a property cache installed when instantiated.
- bool isFullyDynamicType;
+ int coreIndex() const
+ {
+ if (index == -1)
+ return -1;
+ return index & 0xffff;
+ }
- QQmlPropertyCache *propertyCache() const;
- QQmlPropertyCache *createPropertyCache(QQmlEngine *);
+ int valueTypeIndex() const
+ {
+ if (index == -1)
+ return -1;
+ return (index >> 16) - 1;
+ }
- void doDynamicTypeCheck();
- };
- // map from name index
- QHash<int, TypeReference*> resolvedTypes;
+ bool hasValueTypeIndex() const
+ {
+ if (index == -1)
+ return false;
+ return index >> 16;
+ }
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
+ qint32 toEncoded() const
+ { return index; }
- bool isInitialized() const { return hasEngine(); }
- void initialize(QQmlEngine *);
+ int intValue() const
+ { return index; }
-protected:
- virtual void destroy(); // From QQmlRefCount
- virtual void clear(); // From QQmlCleanup
+ bool operator==(const QQmlPropertyIndex &other) const
+ { return index == other.index; }
+
+ bool operator!=(const QQmlPropertyIndex &other) const
+ { return !operator==(other); }
private:
- QQmlCompiledData(const QQmlCompiledData &other);
- QQmlCompiledData &operator=(const QQmlCompiledData &other);
+ static qint32 encode(int coreIndex, int valueTypeIndex)
+ {
+ Q_ASSERT(coreIndex >= -1);
+ Q_ASSERT(coreIndex <= 0xffff);
+ Q_ASSERT(valueTypeIndex >= -1);
+ Q_ASSERT(valueTypeIndex < 0xffff);
+
+ if (coreIndex == -1)
+ return -1;
+ else
+ return coreIndex | ((valueTypeIndex + 1) << 16);
+ }
};
QT_END_NAMESPACE
-#endif // QQMLCOMPILER_P_H
+#endif // QQMLPROPERTYINDEX_P_H
diff --git a/src/qml/qml/qqmlpropertyvalueinterceptor_p.h b/src/qml/qml/qqmlpropertyvalueinterceptor_p.h
index 0c10d13aea..a3d6b0c8c7 100644
--- a/src/qml/qml/qqmlpropertyvalueinterceptor_p.h
+++ b/src/qml/qml/qqmlpropertyvalueinterceptor_p.h
@@ -52,6 +52,7 @@
//
#include <private/qtqmlglobal_p.h>
+#include <private/qqmlpropertyindex_p.h>
#include <QtCore/qobject.h>
QT_BEGIN_NAMESPACE
@@ -68,8 +69,7 @@ public:
private:
friend class QQmlInterceptorMetaObject;
- int m_coreIndex;
- int m_valueTypeCoreIndex;
+ QQmlPropertyIndex m_propertyIndex;
QQmlPropertyValueInterceptor *m_next;
};
diff --git a/src/qml/qml/qqmlproxymetaobject.cpp b/src/qml/qml/qqmlproxymetaobject.cpp
index bbaab1e155..27e3c13ff8 100644
--- a/src/qml/qml/qqmlproxymetaobject.cpp
+++ b/src/qml/qml/qqmlproxymetaobject.cpp
@@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE
QQmlProxyMetaObject::QQmlProxyMetaObject(QObject *obj, QList<ProxyData> *mList)
: metaObjects(mList), proxies(0), parent(0), object(obj)
{
- *static_cast<QMetaObject *>(this) = *metaObjects->first().metaObject;
+ *static_cast<QMetaObject *>(this) = *metaObjects->constFirst().metaObject;
QObjectPrivate *op = QObjectPrivate::get(obj);
if (op->metaObject)
@@ -71,7 +71,7 @@ int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void
if ((c == QMetaObject::ReadProperty ||
c == QMetaObject::WriteProperty) &&
- id >= metaObjects->last().propertyOffset) {
+ id >= metaObjects->constLast().propertyOffset) {
for (int ii = 0; ii < metaObjects->count(); ++ii) {
const ProxyData &data = metaObjects->at(ii);
@@ -107,7 +107,7 @@ int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void
}
}
} else if (c == QMetaObject::InvokeMetaMethod &&
- id >= metaObjects->last().methodOffset) {
+ id >= metaObjects->constLast().methodOffset) {
QMetaMethod m = object->metaObject()->method(id);
if (m.methodType() == QMetaMethod::Signal) {
QMetaObject::activate(object, id, a);
diff --git a/src/qml/qml/qqmlproxymetaobject_p.h b/src/qml/qml/qqmlproxymetaobject_p.h
index 7083f88fa7..2b7a980361 100644
--- a/src/qml/qml/qqmlproxymetaobject_p.h
+++ b/src/qml/qml/qqmlproxymetaobject_p.h
@@ -74,10 +74,10 @@ public:
};
QQmlProxyMetaObject(QObject *, QList<ProxyData> *);
- virtual ~QQmlProxyMetaObject();
+ ~QQmlProxyMetaObject();
protected:
- virtual int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a);
+ int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) override;
private:
QList<ProxyData> *metaObjects;
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 4ec3dfe6a5..b576366abf 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -45,14 +45,17 @@
#include <private/qqmlengine_p.h>
#include <private/qqmlglobal_p.h>
#include <private/qqmlthread_p.h>
-#include <private/qqmlcompiler_p.h>
#include <private/qqmlcomponent_p.h>
#include <private/qqmlprofiler_p.h>
#include <private/qqmlmemoryprofiler_p.h>
#include <private/qqmltypecompiler_p.h>
+#include <private/qqmlpropertyvalidator_p.h>
+#include <private/qqmlpropertycachecreator_p.h>
+#include <private/qdeferredcleanup_p.h>
#include <QtCore/qdir.h>
#include <QtCore/qfile.h>
+#include <QtCore/qdatetime.h>
#include <QtCore/qdebug.h>
#include <QtCore/qmutex.h>
#include <QtCore/qthread.h>
@@ -60,8 +63,11 @@
#include <QtCore/qdiriterator.h>
#include <QtQml/qqmlcomponent.h>
#include <QtCore/qwaitcondition.h>
+#include <QtCore/qloggingcategory.h>
#include <QtQml/qqmlextensioninterface.h>
+#include <functional>
+
#if defined (Q_OS_UNIX)
#include <sys/types.h>
#include <sys/stat.h>
@@ -98,6 +104,11 @@
#endif
DEFINE_BOOL_CONFIG_OPTION(dumpErrors, QML_DUMP_ERRORS);
+DEFINE_BOOL_CONFIG_OPTION(disableDiskCache, QML_DISABLE_DISK_CACHE);
+DEFINE_BOOL_CONFIG_OPTION(forceDiskCache, QML_FORCE_DISK_CACHE);
+
+Q_DECLARE_LOGGING_CATEGORY(DBG_DISK_CACHE)
+Q_LOGGING_CATEGORY(DBG_DISK_CACHE, "qt.qml.diskcache")
QT_BEGIN_NAMESPACE
@@ -155,7 +166,7 @@ public:
void initializeEngine(QQmlExtensionInterface *, const char *);
protected:
- virtual void shutdownThread();
+ void shutdownThread() override;
private:
void loadThread(QQmlDataBlob *b);
@@ -435,6 +446,39 @@ void QQmlDataBlob::setError(const QList<QQmlError> &errors)
tryDone();
}
+void QQmlDataBlob::setError(const QQmlCompileError &error)
+{
+ QQmlError e;
+ e.setColumn(error.location.column);
+ e.setLine(error.location.line);
+ e.setDescription(error.description);
+ e.setUrl(url());
+ setError(e);
+}
+
+void QQmlDataBlob::setError(const QVector<QQmlCompileError> &errors)
+{
+ QList<QQmlError> finalErrors;
+ finalErrors.reserve(errors.count());
+ for (const QQmlCompileError &error: errors) {
+ QQmlError e;
+ e.setColumn(error.location.column);
+ e.setLine(error.location.line);
+ e.setDescription(error.description);
+ e.setUrl(url());
+ finalErrors << e;
+ }
+ setError(finalErrors);
+}
+
+void QQmlDataBlob::setError(const QString &description)
+{
+ QQmlError e;
+ e.setDescription(description);
+ e.setUrl(finalUrl());
+ setError(e);
+}
+
/*!
Wait for \a blob to become complete or to error. If \a blob is already
complete or in error, or this blob is already complete, this has no effect.
@@ -1081,13 +1125,9 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob)
QML_MEMORY_SCOPE_URL(blob->m_url);
if (QQmlFile::isSynchronous(blob->m_url)) {
- QQmlFile file(m_engine, blob->m_url);
-
- if (file.isError()) {
- QQmlError error;
- error.setUrl(blob->m_url);
- error.setDescription(file.error());
- blob->setError(error);
+ const QString fileName = QQmlFile::urlToLocalFileOrQrc(blob->m_url);
+ if (!QQml_isFileCaseCorrect(fileName)) {
+ blob->setError(QLatin1String("File name case mismatch"));
return;
}
@@ -1095,7 +1135,7 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob)
if (blob->m_data.isAsync())
m_thread->callDownloadProgressChanged(blob, 1.);
- setData(blob, &file);
+ setData(blob, fileName);
} else {
#ifndef QT_NO_NETWORK
@@ -1215,11 +1255,11 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QByteArray &data)
setData(blob, d);
}
-void QQmlTypeLoader::setData(QQmlDataBlob *blob, QQmlFile *file)
+void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QString &fileName)
{
QML_MEMORY_SCOPE_URL(blob->url());
QQmlDataBlob::Data d;
- d.d = file;
+ d.d = &fileName;
setData(blob, d);
}
@@ -1270,7 +1310,7 @@ void QQmlTypeLoader::shutdownThread()
}
QQmlTypeLoader::Blob::Blob(const QUrl &url, QQmlDataBlob::Type type, QQmlTypeLoader *loader)
- : QQmlDataBlob(url, type, loader), m_importCache(loader), m_isSingleton(false)
+ : QQmlDataBlob(url, type, loader), m_importCache(loader)
{
}
@@ -1324,7 +1364,8 @@ bool QQmlTypeLoader::Blob::updateQmldir(QQmlQmldirData *data, const QV4::Compile
// Does this library contain any qualified scripts?
QUrl libraryUrl(qmldirUrl);
const QmldirContent *qmldir = typeLoader()->qmldirContent(qmldirIdentifier);
- foreach (const QQmlDirParser::Script &script, qmldir->scripts()) {
+ const auto qmldirScripts = qmldir->scripts();
+ for (const QQmlDirParser::Script &script : qmldirScripts) {
QUrl scriptUrl = libraryUrl.resolved(QUrl(script.fileName));
QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
addDependency(blob);
@@ -1371,7 +1412,8 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
// Does this library contain any qualified scripts?
QUrl libraryUrl(qmldirUrl);
const QmldirContent *qmldir = typeLoader()->qmldirContent(qmldirFilePath);
- foreach (const QQmlDirParser::Script &script, qmldir->scripts()) {
+ const auto qmldirScripts = qmldir->scripts();
+ for (const QQmlDirParser::Script &script : qmldirScripts) {
QUrl scriptUrl = libraryUrl.resolved(QUrl(script.fileName));
QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
addDependency(blob);
@@ -1412,13 +1454,10 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
bool incomplete = false;
- QUrl qmldirUrl;
- if (importQualifier.isEmpty()) {
- qmldirUrl = finalUrl().resolved(QUrl(importUri + QLatin1String("/qmldir")));
- if (!QQmlImports::isLocal(qmldirUrl)) {
- // This is a remote file; the import is currently incomplete
- incomplete = true;
- }
+ QUrl qmldirUrl = finalUrl().resolved(QUrl(importUri + QLatin1String("/qmldir")));
+ if (!QQmlImports::isLocal(qmldirUrl)) {
+ // This is a remote file; the import is currently incomplete
+ incomplete = true;
}
if (!m_importCache.addFileImport(importDatabase, importUri, importQualifier, import->majorVersion,
@@ -1434,51 +1473,6 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
return true;
}
-bool QQmlTypeLoader::Blob::addPragma(const QmlIR::Pragma &pragma, QList<QQmlError> *errors)
-{
- Q_ASSERT(errors);
-
- if (pragma.type == QmlIR::Pragma::PragmaSingleton) {
- QUrl myUrl = finalUrl();
-
- QQmlType *ret = QQmlMetaType::qmlType(myUrl, true);
- if (!ret) {
- QQmlError error;
- error.setDescription(QQmlTypeLoader::tr("No matching type found, pragma Singleton files cannot be used by QQmlComponent."));
- error.setUrl(myUrl);
- error.setLine(pragma.location.line);
- error.setColumn(pragma.location.column);
- errors->prepend(error);
- return false;
- }
-
- if (!ret->isCompositeSingleton()) {
- QQmlError error;
- error.setDescription(QQmlTypeLoader::tr("pragma Singleton used with a non composite singleton type %1").arg(ret->qmlTypeName()));
- error.setUrl(myUrl);
- error.setLine(pragma.location.line);
- error.setColumn(pragma.location.column);
- errors->prepend(error);
- return false;
- }
- // This flag is used for error checking when a qmldir file marks a type as
- // composite singleton, but there is no pragma Singleton defined in QML.
- m_isSingleton = true;
- } else {
- QQmlError error;
- error.setDescription(QLatin1String("Invalid pragma"));
- error.setUrl(finalUrl());
- error.setLine(pragma.location.line);
- error.setColumn(pragma.location.column);
- errors->prepend(error);
- return false;
- }
-
- return true;
-}
-
-
-
void QQmlTypeLoader::Blob::dependencyError(QQmlDataBlob *blob)
{
if (blob->type() == QQmlDataBlob::QmldirFile) {
@@ -1507,6 +1501,11 @@ void QQmlTypeLoader::Blob::dependencyComplete(QQmlDataBlob *blob)
}
}
+bool QQmlTypeLoader::Blob::isDebugging() const
+{
+ return QV8Engine::getV4(typeLoader()->engine())->debugger() != 0;
+}
+
bool QQmlTypeLoader::Blob::qmldirDataAvailable(QQmlQmldirData *data, QList<QQmlError> *errors)
{
bool resolve = true;
@@ -1968,7 +1967,13 @@ void QQmlTypeLoader::trimCache()
QList<TypeCache::Iterator> unneededTypes;
for (TypeCache::Iterator iter = m_typeCache.begin(), end = m_typeCache.end(); iter != end; ++iter) {
QQmlTypeData *typeData = iter.value();
- if (typeData->m_compiledData && typeData->m_compiledData->count() == 1) {
+
+ const bool hasError = !typeData->m_compiledData && !typeData->m_errors.isEmpty();
+ const bool isNotReferenced = typeData->isComplete() && typeData->m_compiledData
+ && typeData->m_compiledData->count() == 1;
+ // typeData->m_compiledData may be set early on in the proccess of loading a file, so it's important
+ // to check the general loading status of the typeData before making any other decisions.
+ if (typeData->count() == 1 && (hasError || isNotReferenced)) {
// There are no live objects of this type
unneededTypes.append(iter);
}
@@ -1978,8 +1983,7 @@ void QQmlTypeLoader::trimCache()
break;
while (!unneededTypes.isEmpty()) {
- TypeCache::Iterator iter = unneededTypes.last();
- unneededTypes.removeLast();
+ TypeCache::Iterator iter = unneededTypes.takeLast();
iter.value()->release();
m_typeCache.erase(iter);
@@ -2009,7 +2013,7 @@ QQmlTypeData::TypeDataCallback::~TypeDataCallback()
QQmlTypeData::QQmlTypeData(const QUrl &url, QQmlTypeLoader *manager)
: QQmlTypeLoader::Blob(url, QmlFile, manager),
- m_typesResolved(false), m_compiledData(0), m_implicitImport(0), m_implicitImportLoaded(false)
+ m_typesResolved(false), m_implicitImportLoaded(false)
{
}
@@ -2022,14 +2026,11 @@ QQmlTypeData::~QQmlTypeData()
if (QQmlTypeData *tdata = m_compositeSingletons.at(ii).typeData)
tdata->release();
}
- for (QHash<int, TypeReference>::ConstIterator it = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd();
+ for (auto it = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd();
it != end; ++it) {
if (QQmlTypeData *tdata = it->typeData)
tdata->release();
}
-
- if (m_compiledData)
- m_compiledData->release();
}
const QList<QQmlTypeData::ScriptReference> &QQmlTypeData::resolvedScripts() const
@@ -2037,19 +2038,9 @@ const QList<QQmlTypeData::ScriptReference> &QQmlTypeData::resolvedScripts() cons
return m_scripts;
}
-const QSet<QString> &QQmlTypeData::namespaces() const
-{
- return m_namespaces;
-}
-
-const QList<QQmlTypeData::TypeReference> &QQmlTypeData::compositeSingletons() const
-{
- return m_compositeSingletons;
-}
-
-QQmlCompiledData *QQmlTypeData::compiledData() const
+QV4::CompiledData::CompilationUnit *QQmlTypeData::compilationUnit() const
{
- return m_compiledData;
+ return m_compiledData.data();
}
void QQmlTypeData::registerCallback(TypeDataCallback *callback)
@@ -2065,10 +2056,115 @@ void QQmlTypeData::unregisterCallback(TypeDataCallback *callback)
Q_ASSERT(!m_callbacks.contains(callback));
}
+bool QQmlTypeData::tryLoadFromDiskCache()
+{
+ if (disableDiskCache() && !forceDiskCache())
+ return false;
+
+ if (isDebugging())
+ return false;
+
+ QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(typeLoader()->engine());
+ if (!v4)
+ return false;
+
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = v4->iselFactory->createUnitForLoading();
+ {
+ QString error;
+ if (!unit->loadFromDisk(url(), v4->iselFactory.data(), &error)) {
+ qCDebug(DBG_DISK_CACHE) << "Error loading" << url().toString() << "from disk cache:" << error;
+ return false;
+ }
+ }
+
+ m_compiledData = unit;
+
+ for (int i = 0, count = m_compiledData->objectCount(); i < count; ++i)
+ m_typeReferences.collectFromObject(m_compiledData->objectAt(i));
+
+ m_importCache.setBaseUrl(finalUrl(), finalUrlString());
+
+ // For remote URLs, we don't delay the loading of the implicit import
+ // because the loading probably requires an asynchronous fetch of the
+ // qmldir (so we can't load it just in time).
+ if (!finalUrl().scheme().isEmpty()) {
+ QUrl qmldirUrl = finalUrl().resolved(QUrl(QLatin1String("qmldir")));
+ if (!QQmlImports::isLocal(qmldirUrl)) {
+ if (!loadImplicitImport())
+ return false;
+
+ // find the implicit import
+ for (quint32 i = 0; i < m_compiledData->data->nImports; ++i) {
+ const QV4::CompiledData::Import *import = m_compiledData->data->importAt(i);
+ if (m_compiledData->stringAt(import->uriIndex) == QLatin1String(".")
+ && import->qualifierIndex == 0
+ && import->majorVersion == -1
+ && import->minorVersion == -1) {
+ QList<QQmlError> errors;
+ if (!fetchQmldir(qmldirUrl, import, 1, &errors)) {
+ setError(errors);
+ return false;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ for (int i = 0, count = m_compiledData->data->nImports; i < count; ++i) {
+ const QV4::CompiledData::Import *import = m_compiledData->data->importAt(i);
+ QList<QQmlError> errors;
+ if (!addImport(import, &errors)) {
+ Q_ASSERT(errors.size());
+ QQmlError error(errors.takeFirst());
+ error.setUrl(m_importCache.baseUrl());
+ error.setLine(import->location.line);
+ error.setColumn(import->location.column);
+ errors.prepend(error); // put it back on the list after filling out information.
+ setError(errors);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeNameCache> &importCache,
+ const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache)
+{
+ Q_ASSERT(m_compiledData);
+ m_compiledData->importCache = importCache;
+ m_compiledData->resolvedTypes = resolvedTypeCache;
+
+ QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine());
+
+ {
+ QQmlPropertyCacheCreator<QV4::CompiledData::CompilationUnit> propertyCacheCreator(&m_compiledData->propertyCaches, engine, m_compiledData, &m_importCache);
+ QQmlCompileError error = propertyCacheCreator.buildMetaObjects();
+ if (error.isSet()) {
+ setError(error);
+ return;
+ }
+ }
+
+ QQmlPropertyCacheAliasCreator<QV4::CompiledData::CompilationUnit> aliasCreator(&m_compiledData->propertyCaches, m_compiledData);
+ aliasCreator.appendAliasPropertiesToMetaObjects();
+}
+
void QQmlTypeData::done()
{
+ QDeferredCleanup cleanup([this]{
+ m_document.reset();
+ m_typeReferences.clear();
+ if (isError())
+ m_compiledData = nullptr;
+ });
+
+ if (isError())
+ return;
+
// Check all script dependencies for errors
- for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) {
+ for (int ii = 0; ii < m_scripts.count(); ++ii) {
const ScriptReference &script = m_scripts.at(ii);
Q_ASSERT(script.script->isCompleteOrError());
if (script.script->isError()) {
@@ -2080,16 +2176,17 @@ void QQmlTypeData::done()
error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->url().toString()));
errors.prepend(error);
setError(errors);
+ return;
}
}
// Check all type dependencies for errors
- for (QHash<int, TypeReference>::ConstIterator it = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd();
- !isError() && it != end; ++it) {
+ for (auto it = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd(); it != end;
+ ++it) {
const TypeReference &type = *it;
Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError());
if (type.typeData && type.typeData->isError()) {
- QString typeName = m_document->stringAt(it.key());
+ const QString typeName = stringAt(it.key());
QList<QQmlError> errors = type.typeData->errors();
QQmlError error;
@@ -2099,11 +2196,12 @@ void QQmlTypeData::done()
error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
errors.prepend(error);
setError(errors);
+ return;
}
}
// Check all composite singleton type dependencies for errors
- for (int ii = 0; !isError() && ii < m_compositeSingletons.count(); ++ii) {
+ for (int ii = 0; ii < m_compositeSingletons.count(); ++ii) {
const TypeReference &type = m_compositeSingletons.at(ii);
Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError());
if (type.typeData && type.typeData->isError()) {
@@ -2117,27 +2215,101 @@ void QQmlTypeData::done()
error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
errors.prepend(error);
setError(errors);
+ return;
}
}
- // If the type is CompositeSingleton but there was no pragma Singleton in the
- // QML file, lets report an error.
- QQmlType *type = QQmlMetaType::qmlType(url(), true);
- if (!isError() && type && type->isCompositeSingleton() && !m_isSingleton) {
- QString typeName = type->qmlTypeName();
+ QQmlRefPointer<QQmlTypeNameCache> importCache;
+ QV4::CompiledData::ResolvedTypeReferenceMap resolvedTypeCache;
+ {
+ QQmlCompileError error = buildTypeResolutionCaches(&importCache, &resolvedTypeCache);
+ if (error.isSet()) {
+ setError(error);
+ return;
+ }
+ }
- QQmlError error;
- error.setDescription(QQmlTypeLoader::tr("qmldir defines type as singleton, but no pragma Singleton found in type %1.").arg(typeName));
- error.setUrl(finalUrl());
- setError(error);
+ QQmlEngine *const engine = typeLoader()->engine();
+
+ // verify if any dependencies changed if we're using a cache
+ if (m_document.isNull() && !m_compiledData->verifyChecksum(engine, resolvedTypeCache)) {
+ if (!loadFromSource())
+ return;
+ m_backupSourceCode.clear();
+ m_compiledData = nullptr;
}
- // Compile component
- if (!isError())
- compile();
+ if (!m_document.isNull()) {
+ // Compile component
+ compile(importCache, resolvedTypeCache);
+ } else {
+ createTypeAndPropertyCaches(importCache, resolvedTypeCache);
+ }
- m_document.reset();
- m_implicitImport = 0;
+ if (isError())
+ return;
+
+ {
+ QQmlEnginePrivate *const enginePrivate = QQmlEnginePrivate::get(engine);
+ {
+ // Sanity check property bindings
+ QQmlPropertyValidator validator(enginePrivate, m_importCache, m_compiledData);
+ QVector<QQmlCompileError> errors = validator.validate();
+ if (!errors.isEmpty()) {
+ setError(errors);
+ return;
+ }
+ }
+
+ m_compiledData->finalize(enginePrivate);
+ }
+
+ {
+ QQmlType *type = QQmlMetaType::qmlType(finalUrl(), true);
+ if (m_compiledData && m_compiledData->data->flags & QV4::CompiledData::Unit::IsSingleton) {
+ if (!type) {
+ QQmlError error;
+ error.setDescription(QQmlTypeLoader::tr("No matching type found, pragma Singleton files cannot be used by QQmlComponent."));
+ setError(error);
+ return;
+ } else if (!type->isCompositeSingleton()) {
+ QQmlError error;
+ error.setDescription(QQmlTypeLoader::tr("pragma Singleton used with a non composite singleton type %1").arg(type->qmlTypeName()));
+ setError(error);
+ return;
+ }
+ } else {
+ // If the type is CompositeSingleton but there was no pragma Singleton in the
+ // QML file, lets report an error.
+ if (type && type->isCompositeSingleton()) {
+ QString typeName = type->qmlTypeName();
+ setError(QQmlTypeLoader::tr("qmldir defines type as singleton, but no pragma Singleton found in type %1.").arg(typeName));
+ return;
+ }
+ }
+ }
+
+ {
+ // Collect imported scripts
+ m_compiledData->dependentScripts.reserve(m_scripts.count());
+ for (int scriptIndex = 0; scriptIndex < m_scripts.count(); ++scriptIndex) {
+ const QQmlTypeData::ScriptReference &script = m_scripts.at(scriptIndex);
+
+ QStringRef qualifier(&script.qualifier);
+ QString enclosingNamespace;
+
+ const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.'));
+ if (lastDotIndex != -1) {
+ enclosingNamespace = qualifier.left(lastDotIndex).toString();
+ qualifier = qualifier.mid(lastDotIndex+1);
+ }
+
+ m_compiledData->importCache->add(qualifier.toString(), scriptIndex, enclosingNamespace);
+ QQmlScriptData *scriptData = script.script->scriptData();
+ scriptData->addref();
+ m_compiledData->dependentScripts << scriptData;
+ }
+ }
}
void QQmlTypeData::completed()
@@ -2172,14 +2344,47 @@ bool QQmlTypeData::loadImplicitImport()
void QQmlTypeData::dataReceived(const Data &data)
{
- QString code = QString::fromUtf8(data.data(), data.size());
+ QString error;
+ m_backupSourceCode = data.readAll(&error, &m_sourceTimeStamp);
+ // if we failed to read the source code, process it _after_ we've tried
+ // to use the disk cache, in order to support scenarios where the source
+ // was removed deliberately.
+
+ if (tryLoadFromDiskCache())
+ return;
+
+ if (isError())
+ return;
+
+ if (!error.isEmpty()) {
+ setError(error);
+ return;
+ }
+
+ if (!loadFromSource())
+ return;
+
+ continueLoadFromIR();
+}
+
+void QQmlTypeData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit)
+{
+ m_document.reset(new QmlIR::Document(isDebugging()));
+ unit->loadIR(m_document.data(), unit);
+ continueLoadFromIR();
+}
+
+bool QQmlTypeData::loadFromSource()
+{
+ QString code = QString::fromUtf8(m_backupSourceCode);
+ m_document.reset(new QmlIR::Document(isDebugging()));
+ m_document->jsModule.sourceTimeStamp = m_sourceTimeStamp;
QQmlEngine *qmlEngine = typeLoader()->engine();
- m_document.reset(new QmlIR::Document(QV8Engine::getV4(qmlEngine)->debugger != 0));
QmlIR::IRBuilder compiler(QV8Engine::get(qmlEngine)->illegalNames());
if (!compiler.generateFromQml(code, finalUrlString(), m_document.data())) {
QList<QQmlError> errors;
errors.reserve(compiler.errors.count());
- foreach (const QQmlJS::DiagnosticMessage &msg, compiler.errors) {
+ for (const QQmlJS::DiagnosticMessage &msg : qAsConst(compiler.errors)) {
QQmlError e;
e.setUrl(finalUrl());
e.setLine(msg.loc.startLine);
@@ -2188,23 +2393,14 @@ void QQmlTypeData::dataReceived(const Data &data)
errors << e;
}
setError(errors);
- return;
+ return false;
}
-
- continueLoadFromIR();
-}
-
-void QQmlTypeData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit)
-{
- QQmlEngine *qmlEngine = typeLoader()->engine();
- m_document.reset(new QmlIR::Document(QV8Engine::getV4(qmlEngine)->debugger != 0));
- unit->loadIR(m_document.data(), unit);
- continueLoadFromIR();
+ return true;
}
void QQmlTypeData::continueLoadFromIR()
{
- m_document->collectTypeReferences();
+ m_typeReferences.collectFromObjects(m_document->objects.constBegin(), m_document->objects.constEnd());
m_importCache.setBaseUrl(finalUrl(), finalUrlString());
// For remote URLs, we don't delay the loading of the implicit import
@@ -2217,14 +2413,14 @@ void QQmlTypeData::continueLoadFromIR()
return;
// This qmldir is for the implicit import
QQmlJS::MemoryPool *pool = m_document->jsParserEngine.pool();
- m_implicitImport = pool->New<QV4::CompiledData::Import>();
- m_implicitImport->uriIndex = m_document->registerString(QLatin1String("."));
- m_implicitImport->qualifierIndex = 0; // empty string
- m_implicitImport->majorVersion = -1;
- m_implicitImport->minorVersion = -1;
+ auto implicitImport = pool->New<QV4::CompiledData::Import>();
+ implicitImport->uriIndex = m_document->registerString(QLatin1String("."));
+ implicitImport->qualifierIndex = 0; // empty string
+ implicitImport->majorVersion = -1;
+ implicitImport->minorVersion = -1;
QList<QQmlError> errors;
- if (!fetchQmldir(qmldirUrl, m_implicitImport, 1, &errors)) {
+ if (!fetchQmldir(qmldirUrl, implicitImport, 1, &errors)) {
setError(errors);
return;
}
@@ -2245,14 +2441,6 @@ void QQmlTypeData::continueLoadFromIR()
return;
}
}
-
- foreach (QmlIR::Pragma *pragma, m_document->pragmas) {
- if (!addPragma(*pragma, &errors)) {
- Q_ASSERT(errors.size());
- setError(errors);
- return;
- }
- }
}
void QQmlTypeData::allDependenciesDone()
@@ -2297,40 +2485,54 @@ void QQmlTypeData::downloadProgressChanged(qreal p)
QString QQmlTypeData::stringAt(int index) const
{
+ if (m_compiledData)
+ return m_compiledData->stringAt(index);
return m_document->jsGenerator.stringTable.stringForIndex(index);
}
-void QQmlTypeData::compile()
+void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &importCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache)
{
- Q_ASSERT(m_compiledData == 0);
-
- m_compiledData = new QQmlCompiledData(typeLoader()->engine());
+ Q_ASSERT(m_compiledData.isNull());
- QQmlTypeCompiler compiler(QQmlEnginePrivate::get(typeLoader()->engine()), m_compiledData, this, m_document.data());
- if (!compiler.compile()) {
+ QQmlEnginePrivate * const enginePrivate = QQmlEnginePrivate::get(typeLoader()->engine());
+ QQmlTypeCompiler compiler(enginePrivate, this, m_document.data(), importCache, resolvedTypeCache);
+ m_compiledData = compiler.compile();
+ if (!m_compiledData) {
setError(compiler.compilationErrors());
- m_compiledData->release();
- m_compiledData = 0;
+ return;
+ }
+
+ const bool trySaveToDisk = (!disableDiskCache() || forceDiskCache()) && !m_document->jsModule.debugMode;
+ if (trySaveToDisk) {
+ QString errorString;
+ if (m_compiledData->saveToDisk(url(), &errorString)) {
+ QString error;
+ if (!m_compiledData->loadFromDisk(url(), enginePrivate->v4engine()->iselFactory.data(), &error)) {
+ // ignore error, keep using the in-memory compilation unit.
+ }
+ } else {
+ qCDebug(DBG_DISK_CACHE) << "Error saving cached version of" << m_compiledData->url().toString() << "to disk:" << errorString;
+ }
}
}
void QQmlTypeData::resolveTypes()
{
// Add any imported scripts to our resolved set
- foreach (const QQmlImports::ScriptReference &script, m_importCache.resolvedScripts())
- {
+ const auto resolvedScripts = m_importCache.resolvedScripts();
+ for (const QQmlImports::ScriptReference &script : resolvedScripts) {
QQmlScriptBlob *blob = typeLoader()->getScript(script.location);
addDependency(blob);
ScriptReference ref;
//ref.location = ...
- ref.qualifier = script.nameSpace;
if (!script.qualifier.isEmpty())
{
- ref.qualifier.prepend(script.qualifier + QLatin1Char('.'));
-
+ ref.qualifier = script.qualifier + QLatin1Char('.') + script.nameSpace;
// Add a reference to the enclosing namespace
m_namespaces.insert(script.qualifier);
+ } else {
+ ref.qualifier = script.nameSpace;
}
ref.script = blob;
@@ -2338,14 +2540,16 @@ void QQmlTypeData::resolveTypes()
}
// Lets handle resolved composite singleton types
- foreach (const QQmlImports::CompositeSingletonReference &csRef, m_importCache.resolvedCompositeSingletons()) {
+ const auto resolvedCompositeSingletons = m_importCache.resolvedCompositeSingletons();
+ for (const QQmlImports::CompositeSingletonReference &csRef : resolvedCompositeSingletons) {
TypeReference ref;
- QString typeName = csRef.typeName;
-
+ QString typeName;
if (!csRef.prefix.isEmpty()) {
- typeName.prepend(csRef.prefix + QLatin1Char('.'));
+ typeName = csRef.prefix + QLatin1Char('.') + csRef.typeName;
// Add a reference to the enclosing namespace
m_namespaces.insert(csRef.prefix);
+ } else {
+ typeName = csRef.typeName;
}
int majorVersion = csRef.majorVersion > -1 ? csRef.majorVersion : -1;
@@ -2363,7 +2567,7 @@ void QQmlTypeData::resolveTypes()
}
}
- for (QV4::CompiledData::TypeReferenceMap::ConstIterator unresolvedRef = m_document->typeReferences.constBegin(), end = m_document->typeReferences.constEnd();
+ for (QV4::CompiledData::TypeReferenceMap::ConstIterator unresolvedRef = m_typeReferences.constBegin(), end = m_typeReferences.constEnd();
unresolvedRef != end; ++unresolvedRef) {
TypeReference ref; // resolved reference
@@ -2433,6 +2637,57 @@ void QQmlTypeData::resolveTypes()
}
}
+QQmlCompileError QQmlTypeData::buildTypeResolutionCaches(
+ QQmlRefPointer<QQmlTypeNameCache> *importCache,
+ QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache
+ ) const
+{
+ importCache->adopt(new QQmlTypeNameCache);
+
+ for (const QString &ns: m_namespaces)
+ (*importCache)->add(ns);
+
+ // Add any Composite Singletons that were used to the import cache
+ for (const QQmlTypeData::TypeReference &singleton: m_compositeSingletons)
+ (*importCache)->add(singleton.type->qmlTypeName(), singleton.type->sourceUrl(), singleton.prefix);
+
+ m_importCache.populateCache(*importCache);
+
+ QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine());
+
+ for (auto resolvedType = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd(); resolvedType != end; ++resolvedType) {
+ QScopedPointer<QV4::CompiledData::ResolvedTypeReference> ref(new QV4::CompiledData::ResolvedTypeReference);
+ QQmlType *qmlType = resolvedType->type;
+ if (resolvedType->typeData) {
+ if (resolvedType->needsCreation && qmlType->isCompositeSingleton()) {
+ return QQmlCompileError(resolvedType->location, tr("Composite Singleton Type %1 is not creatable.").arg(qmlType->qmlTypeName()));
+ }
+ ref->compilationUnit = resolvedType->typeData->compilationUnit();
+ } else if (qmlType) {
+ ref->type = qmlType;
+ Q_ASSERT(ref->type);
+
+ if (resolvedType->needsCreation && !ref->type->isCreatable()) {
+ QString reason = ref->type->noCreationReason();
+ if (reason.isEmpty())
+ reason = tr("Element is not creatable.");
+ return QQmlCompileError(resolvedType->location, reason);
+ }
+
+ if (ref->type->containsRevisionedAttributes()) {
+ ref->typePropertyCache = engine->cache(ref->type,
+ resolvedType->minorVersion);
+ }
+ }
+ ref->majorVersion = resolvedType->majorVersion;
+ ref->minorVersion = resolvedType->minorVersion;
+ ref->doDynamicTypeCheck();
+ resolvedTypeCache->insert(resolvedType.key(), ref.take());
+ }
+ QQmlCompileError noError;
+ return noError;
+}
+
bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref)
{
QQmlImportNamespace *typeNamespace = 0;
@@ -2554,10 +2809,6 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent
ctxt->importedScripts = effectiveCtxt->importedScripts;
}
- if (ctxt->imports) {
- ctxt->imports->addref();
- }
-
if (effectiveCtxt) {
ctxt->setParent(effectiveCtxt, true);
} else {
@@ -2640,15 +2891,34 @@ QQmlScriptData *QQmlScriptBlob::scriptData() const
struct EmptyCompilationUnit : public QV4::CompiledData::CompilationUnit
{
- virtual void linkBackendToEngine(QV4::ExecutionEngine *) {}
+ void linkBackendToEngine(QV4::ExecutionEngine *) override {}
};
void QQmlScriptBlob::dataReceived(const Data &data)
{
- QString source = QString::fromUtf8(data.data(), data.size());
-
QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine());
- QmlIR::Document irUnit(v4->debugger != 0);
+
+ if (!disableDiskCache() || forceDiskCache()) {
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = v4->iselFactory->createUnitForLoading();
+ QString error;
+ if (unit->loadFromDisk(url(), v4->iselFactory.data(), &error)) {
+ initializeFromCompilationUnit(unit);
+ return;
+ } else {
+ qCDebug(DBG_DISK_CACHE()) << "Error loading" << url().toString() << "from disk cache:" << error;
+ }
+ }
+
+
+ QmlIR::Document irUnit(isDebugging());
+
+ QString error;
+ QString source = QString::fromUtf8(data.readAll(&error, &irUnit.jsModule.sourceTimeStamp));
+ if (!error.isEmpty()) {
+ setError(error);
+ return;
+ }
+
QmlIR::ScriptDirectivesCollector collector(&irUnit.jsParserEngine, &irUnit.jsGenerator);
QList<QQmlError> errors;
@@ -2665,14 +2935,22 @@ void QQmlScriptBlob::dataReceived(const Data &data)
irUnit.javaScriptCompilationUnit = unit;
irUnit.imports = collector.imports;
if (collector.hasPragmaLibrary)
- irUnit.unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary;
+ irUnit.jsModule.unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary;
QmlIR::QmlUnitGenerator qmlGenerator;
- QV4::CompiledData::Unit *unitData = qmlGenerator.generate(irUnit);
+ QV4::CompiledData::ResolvedTypeReferenceMap emptyDependencies;
+ QV4::CompiledData::Unit *unitData = qmlGenerator.generate(irUnit, m_typeLoader->engine(), emptyDependencies);
Q_ASSERT(!unit->data);
// The js unit owns the data and will free the qml unit.
unit->data = unitData;
+ if (!disableDiskCache() || forceDiskCache()) {
+ QString errorString;
+ if (!unit->saveToDisk(url(), &errorString)) {
+ qCDebug(DBG_DISK_CACHE()) << "Error saving cached version of" << unit->url().toString() << "to disk:" << errorString;
+ }
+ }
+
initializeFromCompilationUnit(unit);
}
@@ -2683,8 +2961,11 @@ void QQmlScriptBlob::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *
void QQmlScriptBlob::done()
{
+ if (isError())
+ return;
+
// Check all script dependencies for errors
- for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) {
+ for (int ii = 0; ii < m_scripts.count(); ++ii) {
const ScriptReference &script = m_scripts.at(ii);
Q_ASSERT(script.script->isCompleteOrError());
if (script.script->isError()) {
@@ -2696,17 +2977,15 @@ void QQmlScriptBlob::done()
error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->url().toString()));
errors.prepend(error);
setError(errors);
+ return;
}
}
- if (isError())
- return;
-
m_scriptData->importCache = new QQmlTypeNameCache();
QSet<QString> ns;
- for (int scriptIndex = 0; !isError() && scriptIndex < m_scripts.count(); ++scriptIndex) {
+ for (int scriptIndex = 0; scriptIndex < m_scripts.count(); ++scriptIndex) {
const ScriptReference &script = m_scripts.at(scriptIndex);
m_scriptData->scripts.append(script.script);
@@ -2800,7 +3079,12 @@ void QQmlQmldirData::setPriority(int priority)
void QQmlQmldirData::dataReceived(const Data &data)
{
- m_content = QString::fromUtf8(data.data(), data.size());
+ QString error;
+ m_content = QString::fromUtf8(data.readAll(&error));
+ if (!error.isEmpty()) {
+ setError(error);
+ return;
+ }
}
void QQmlQmldirData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *)
@@ -2808,6 +3092,30 @@ void QQmlQmldirData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *
Q_UNIMPLEMENTED();
}
+QByteArray QQmlDataBlob::Data::readAll(QString *error, qint64 *sourceTimeStamp) const
+{
+ Q_ASSERT(!d.isNull());
+ error->clear();
+ if (d.isT1()) {
+ if (sourceTimeStamp)
+ *sourceTimeStamp = 0;
+ return *d.asT1();
+ }
+ QFile f(*d.asT2());
+ if (!f.open(QIODevice::ReadOnly)) {
+ *error = f.errorString();
+ return QByteArray();
+ }
+ if (sourceTimeStamp)
+ *sourceTimeStamp = QFileInfo(f).lastModified().toMSecsSinceEpoch();
+ QByteArray data(f.size(), Qt::Uninitialized);
+ if (f.read(data.data(), data.length()) != data.length()) {
+ *error = f.errorString();
+ return QByteArray();
+ }
+ return data;
+}
+
QT_END_NAMESPACE
#include "qqmltypeloader.moc"
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 12ab98e425..12c55e9179 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -77,11 +77,11 @@ class QQmlScriptData;
class QQmlScriptBlob;
class QQmlQmldirData;
class QQmlTypeLoader;
-class QQmlCompiledData;
class QQmlComponentPrivate;
class QQmlTypeData;
class QQmlTypeLoader;
class QQmlExtensionInterface;
+struct QQmlCompileError;
namespace QmlIR {
struct Document;
@@ -131,27 +131,23 @@ public:
class Data {
public:
- inline const char *data() const;
- inline int size() const;
-
- inline QByteArray asByteArray() const;
-
- inline bool isFile() const;
- inline QQmlFile *asFile() const;
-
+ QByteArray readAll(QString *error, qint64 *sourceTimeStamp = 0) const;
private:
friend class QQmlDataBlob;
friend class QQmlTypeLoader;
inline Data();
Data(const Data &);
Data &operator=(const Data &);
- QBiPointer<const QByteArray, QQmlFile> d;
+ QBiPointer<const QByteArray, const QString> d;
};
protected:
// Can be called from within callbacks
void setError(const QQmlError &);
void setError(const QList<QQmlError> &errors);
+ void setError(const QQmlCompileError &error);
+ void setError(const QVector<QQmlCompileError> &errors);
+ void setError(const QString &description);
void addDependency(QQmlDataBlob *);
// Callbacks made in load thread
@@ -237,7 +233,6 @@ public:
protected:
bool addImport(const QV4::CompiledData::Import *import, QList<QQmlError> *errors);
- bool addPragma(const QmlIR::Pragma &pragma, QList<QQmlError> *errors);
bool fetchQmldir(const QUrl &url, const QV4::CompiledData::Import *import, int priority, QList<QQmlError> *errors);
bool updateQmldir(QQmlQmldirData *data, const QV4::CompiledData::Import *import, QList<QQmlError> *errors);
@@ -247,14 +242,15 @@ public:
virtual void scriptImported(QQmlScriptBlob *, const QV4::CompiledData::Location &, const QString &, const QString &) {}
- virtual void dependencyError(QQmlDataBlob *);
- virtual void dependencyComplete(QQmlDataBlob *);
+ void dependencyError(QQmlDataBlob *) override;
+ void dependencyComplete(QQmlDataBlob *) override;
protected:
virtual QString stringAt(int) const { return QString(); }
+ bool isDebugging() const;
+
QQmlImports m_importCache;
- bool m_isSingleton;
QHash<const QV4::CompiledData::Import*, int> m_unresolvedImports;
QList<QQmlQmldirData *> m_qmldirs;
};
@@ -341,7 +337,7 @@ private:
#endif
void setData(QQmlDataBlob *, const QByteArray &);
- void setData(QQmlDataBlob *, QQmlFile *);
+ void setData(QQmlDataBlob *, const QString &fileName);
void setData(QQmlDataBlob *, const QQmlDataBlob::Data &);
void setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit);
@@ -391,6 +387,7 @@ private:
class Q_AUTOTEST_EXPORT QQmlTypeData : public QQmlTypeLoader::Blob
{
+ Q_DECLARE_TR_FUNCTIONS(QQmlTypeData)
public:
struct TypeReference
{
@@ -422,13 +419,9 @@ private:
public:
~QQmlTypeData();
- const QHash<int, TypeReference> &resolvedTypeRefs() const { return m_resolvedTypes; }
-
const QList<ScriptReference> &resolvedScripts() const;
- const QSet<QString> &namespaces() const;
- const QList<TypeReference> &compositeSingletons() const;
- QQmlCompiledData *compiledData() const;
+ QV4::CompiledData::CompilationUnit *compilationUnit() const;
// Used by QQmlComponent to get notifications
struct TypeDataCallback {
@@ -440,24 +433,37 @@ public:
void unregisterCallback(TypeDataCallback *);
protected:
- virtual void done();
- virtual void completed();
- virtual void dataReceived(const Data &);
- virtual void initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit);
- virtual void allDependenciesDone();
- virtual void downloadProgressChanged(qreal);
+ void done() override;
+ void completed() override;
+ void dataReceived(const Data &) override;
+ void initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit) override;
+ void allDependenciesDone() override;
+ void downloadProgressChanged(qreal) override;
- virtual QString stringAt(int index) const;
+ QString stringAt(int index) const override;
private:
+ bool tryLoadFromDiskCache();
+ bool loadFromSource();
void continueLoadFromIR();
void resolveTypes();
- void compile();
+ QQmlCompileError buildTypeResolutionCaches(
+ QQmlRefPointer<QQmlTypeNameCache> *importCache,
+ QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache
+ ) const;
+ void compile(const QQmlRefPointer<QQmlTypeNameCache> &importCache,
+ const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache);
+ void createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeNameCache> &importCache,
+ const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache);
bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref);
- virtual void scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace);
+ void scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override;
+
+ qint64 m_sourceTimeStamp = 0;
+ QByteArray m_backupSourceCode; // used when cache verification fails.
QScopedPointer<QmlIR::Document> m_document;
+ QV4::CompiledData::TypeReferenceMap m_typeReferences;
QList<ScriptReference> m_scripts;
@@ -465,14 +471,15 @@ private:
QList<TypeReference> m_compositeSingletons;
// map from name index to resolved type
- QHash<int, TypeReference> m_resolvedTypes;
+ // While this could be a hash, a map is chosen here to provide a stable
+ // order, which is used to calculating a check-sum on dependent meta-objects.
+ QMap<int, TypeReference> m_resolvedTypes;
bool m_typesResolved:1;
- QQmlCompiledData *m_compiledData;
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_compiledData;
QList<TypeDataCallback *> m_callbacks;
- QV4::CompiledData::Import *m_implicitImport;
bool m_implicitImportLoaded;
bool loadImplicitImport();
};
@@ -502,7 +509,7 @@ public:
QV4::ReturnedValue scriptValueForContext(QQmlContextData *parentCtxt);
protected:
- virtual void clear(); // From QQmlCleanup
+ void clear() override; // From QQmlCleanup
private:
friend class QQmlScriptBlob;
@@ -538,14 +545,14 @@ public:
QQmlScriptData *scriptData() const;
protected:
- virtual void dataReceived(const Data &);
- virtual void initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit);
- virtual void done();
+ void dataReceived(const Data &) override;
+ void initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit) override;
+ void done() override;
- virtual QString stringAt(int index) const;
+ QString stringAt(int index) const override;
private:
- virtual void scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace);
+ void scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override;
void initializeFromCompilationUnit(QV4::CompiledData::CompilationUnit *unit);
QList<ScriptReference> m_scripts;
@@ -582,40 +589,7 @@ QQmlDataBlob::Data::Data()
{
}
-const char *QQmlDataBlob::Data::data() const
-{
- Q_ASSERT(!d.isNull());
- if (d.isT1()) return d.asT1()->constData();
- else return d.asT2()->data();
-}
-
-int QQmlDataBlob::Data::size() const
-{
- Q_ASSERT(!d.isNull());
-
- if (d.isT1()) return d.asT1()->size();
- else return d.asT2()->size();
-}
-
-bool QQmlDataBlob::Data::isFile() const
-{
- return d.isT2();
-}
-
-QByteArray QQmlDataBlob::Data::asByteArray() const
-{
- Q_ASSERT(!d.isNull());
-
- if (d.isT1()) return *d.asT1();
- else return d.asT2()->dataByteArray();
-}
-
-QQmlFile *QQmlDataBlob::Data::asFile() const
-{
- if (d.isT2()) return d.asT2();
- else return 0;
-}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 7892555f08..28c2588117 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -58,12 +58,14 @@ DEFINE_OBJECT_VTABLE(QmlTypeWrapper);
Heap::QmlTypeWrapper::QmlTypeWrapper()
: mode(IncludeEnums)
{
+ object.init();
}
Heap::QmlTypeWrapper::~QmlTypeWrapper()
{
if (typeNamespace)
typeNamespace->release();
+ object.destroy();
}
bool QmlTypeWrapper::isSingleton() const
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index 8216526cb5..7c5105b184 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -74,7 +74,7 @@ struct QmlTypeWrapper : Object {
QmlTypeWrapper();
~QmlTypeWrapper();
TypeNameMode mode;
- QPointer<QObject> object;
+ QQmlQPointer<QObject> object;
QQmlType *type;
QQmlTypeNameCache *typeNamespace;
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 44fd47244d..bcefad0ee3 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -88,6 +88,7 @@ bool QQmlValueTypeFactoryImpl::isValueType(int idx)
&& idx != QVariant::StringList
&& idx != QMetaType::QObjectStar
&& idx != QMetaType::VoidStar
+ && idx != QMetaType::Nullptr
&& idx != QMetaType::QVariant
&& idx != QMetaType::QLocale) {
return true;
@@ -219,7 +220,7 @@ void QQmlValueType::read(QObject *obj, int idx)
QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
}
-void QQmlValueType::write(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags)
+void QQmlValueType::write(QObject *obj, int idx, QQmlPropertyData::WriteFlags flags)
{
Q_ASSERT(gadgetPtr);
int status = -1;
@@ -259,7 +260,7 @@ int QQmlValueType::metaCall(QObject *, QMetaObject::Call type, int _id, void **a
QString QQmlPointFValueType::toString() const
{
- return QString(QLatin1String("QPointF(%1, %2)")).arg(v.x()).arg(v.y());
+ return QString::asprintf("QPointF(%g, %g)", v.x(), v.y());
}
qreal QQmlPointFValueType::x() const
@@ -306,7 +307,7 @@ void QQmlPointValueType::setY(int y)
QString QQmlSizeFValueType::toString() const
{
- return QString(QLatin1String("QSizeF(%1, %2)")).arg(v.width()).arg(v.height());
+ return QString::asprintf("QSizeF(%g, %g)", v.width(), v.height());
}
qreal QQmlSizeFValueType::width() const
@@ -352,7 +353,7 @@ void QQmlSizeValueType::setHeight(int h)
QString QQmlRectFValueType::toString() const
{
- return QString(QLatin1String("QRectF(%1, %2, %3, %4)")).arg(v.x()).arg(v.y()).arg(v.width()).arg(v.height());
+ return QString::asprintf("QRectF(%g, %g, %g, %g)", v.x(), v.y(), v.width(), v.height());
}
qreal QQmlRectFValueType::x() const
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index 910d39cf0a..0502a5d665 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -69,14 +69,14 @@ public:
QQmlValueType(int userType, const QMetaObject *metaObject);
~QQmlValueType();
void read(QObject *, int);
- void write(QObject *, int, QQmlPropertyPrivate::WriteFlags flags);
+ void write(QObject *, int, QQmlPropertyData::WriteFlags flags);
QVariant value();
void setValue(const QVariant &);
// ---- dynamic meta object data interface
- virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *);
- virtual void objectDestroyed(QObject *);
- virtual int metaCall(QObject *obj, QMetaObject::Call type, int _id, void **argv);
+ QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) override;
+ void objectDestroyed(QObject *) override;
+ int metaCall(QObject *obj, QMetaObject::Call type, int _id, void **argv) override;
// ----
private:
diff --git a/src/qml/qml/qqmlvaluetypeproxybinding.cpp b/src/qml/qml/qqmlvaluetypeproxybinding.cpp
index 6858215a79..56f073121e 100644
--- a/src/qml/qml/qqmlvaluetypeproxybinding.cpp
+++ b/src/qml/qml/qqmlvaluetypeproxybinding.cpp
@@ -41,7 +41,7 @@
QT_BEGIN_NAMESPACE
-QQmlValueTypeProxyBinding::QQmlValueTypeProxyBinding(QObject *o, int index)
+QQmlValueTypeProxyBinding::QQmlValueTypeProxyBinding(QObject *o, QQmlPropertyIndex index)
: QQmlAbstractBinding(),
m_bindings(0)
{
@@ -58,7 +58,7 @@ QQmlValueTypeProxyBinding::~QQmlValueTypeProxyBinding()
}
}
-void QQmlValueTypeProxyBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags)
+void QQmlValueTypeProxyBinding::setEnabled(bool e, QQmlPropertyData::WriteFlags flags)
{
QQmlAbstractBinding *b = m_bindings.data();
while (b) {
@@ -72,7 +72,7 @@ bool QQmlValueTypeProxyBinding::isValueTypeProxy() const
return true;
}
-QQmlAbstractBinding *QQmlValueTypeProxyBinding::binding(int propertyIndex)
+QQmlAbstractBinding *QQmlValueTypeProxyBinding::binding(QQmlPropertyIndex propertyIndex)
{
QQmlAbstractBinding *binding = m_bindings.data();
@@ -91,7 +91,7 @@ void QQmlValueTypeProxyBinding::removeBindings(quint32 mask)
QQmlAbstractBinding *lastBinding = 0;
while (binding) {
- int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(binding->targetPropertyIndex());
+ const int valueTypeIndex = binding->targetPropertyIndex().valueTypeIndex();
if (valueTypeIndex != -1 && (mask & (1 << valueTypeIndex))) {
QQmlAbstractBinding *remove = binding;
remove->setAddedToObject(false);
diff --git a/src/qml/qml/qqmlvaluetypeproxybinding_p.h b/src/qml/qml/qqmlvaluetypeproxybinding_p.h
index de5acc2984..aa7abaa486 100644
--- a/src/qml/qml/qqmlvaluetypeproxybinding_p.h
+++ b/src/qml/qml/qqmlvaluetypeproxybinding_p.h
@@ -58,13 +58,13 @@ QT_BEGIN_NAMESPACE
class QQmlValueTypeProxyBinding : public QQmlAbstractBinding
{
public:
- QQmlValueTypeProxyBinding(QObject *o, int coreIndex);
+ QQmlValueTypeProxyBinding(QObject *o, QQmlPropertyIndex coreIndex);
- QQmlAbstractBinding *binding(int targetPropertyIndex);
+ QQmlAbstractBinding *binding(QQmlPropertyIndex targetPropertyIndex);
void removeBindings(quint32 mask);
- virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags);
- virtual bool isValueTypeProxy() const;
+ void setEnabled(bool, QQmlPropertyData::WriteFlags) override;
+ bool isValueTypeProxy() const override;
protected:
~QQmlValueTypeProxyBinding();
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 5cb346a462..6b308374e6 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -63,8 +63,9 @@ namespace Heap {
struct QQmlValueTypeReference : QQmlValueTypeWrapper
{
- QQmlValueTypeReference() {}
- QPointer<QObject> object;
+ QQmlValueTypeReference() { object.init(); }
+ ~QQmlValueTypeReference() { object.destroy(); }
+ QQmlQPointer<QObject> object;
int property;
};
@@ -332,7 +333,8 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
if (QMetaType::convert(w->d()->gadgetPtr, w->d()->valueType->typeId, &convertResult, QMetaType::QString)) {
result = convertResult;
} else {
- result = QString::fromUtf8(QMetaType::typeName(w->d()->valueType->typeId)) + QLatin1Char('(');
+ result += QString::fromUtf8(QMetaType::typeName(w->d()->valueType->typeId))
+ + QLatin1Char('(');
const QMetaObject *mo = w->d()->propertyCache->metaObject();
const int propCount = mo->propertyCount();
for (int i = 0; i < propCount; ++i) {
@@ -369,10 +371,10 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
if (result->isFunction())
// calling a Q_INVOKABLE function of a value type
- return QV4::QObjectMethod::create(v4->rootContext(), r, result->coreIndex);
+ return QV4::QObjectMethod::create(v4->rootContext(), r, result->coreIndex());
#define VALUE_TYPE_LOAD(metatype, cpptype, constructor) \
- if (result->propType == metatype) { \
+ if (result->propType() == metatype) { \
cpptype v; \
void *args[] = { &v, 0 }; \
metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, index, args); \
@@ -381,7 +383,7 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
const QMetaObject *metaObject = r->d()->propertyCache->metaObject();
- int index = result->coreIndex;
+ int index = result->coreIndex();
QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(QMetaObject::ReadProperty, &metaObject, &index);
void *gadget = r->d()->gadgetPtr;
@@ -394,10 +396,10 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
QVariant v;
void *args[] = { Q_NULLPTR, Q_NULLPTR };
- if (result->propType == QMetaType::QVariant) {
+ if (result->propType() == QMetaType::QVariant) {
args[0] = &v;
} else {
- v = QVariant(result->propType, static_cast<void *>(Q_NULLPTR));
+ v = QVariant(result->propType(), static_cast<void *>(Q_NULLPTR));
args[0] = v.data();
}
metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, index, args);
@@ -431,8 +433,6 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
const QQmlPropertyData *pd = r->d()->propertyCache->property(name, 0, 0);
if (!pd)
return;
- QMetaProperty property = metaObject->property(pd->coreIndex);
- Q_ASSERT(property.isValid());
if (reference) {
QV4::ScopedFunctionObject f(scope, value);
@@ -448,27 +448,24 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
QQmlContextData *context = v4->callingQmlContext();
QQmlPropertyData cacheData;
- cacheData.setFlags(QQmlPropertyData::IsWritable |
- QQmlPropertyData::IsValueTypeVirtual);
- cacheData.propType = writeBackPropertyType;
- cacheData.coreIndex = reference->d()->property;
- cacheData.valueTypeFlags = 0;
- cacheData.valueTypeCoreIndex = pd->coreIndex;
- cacheData.valueTypePropType = property.userType();
+ cacheData.setWritable(true);
+ cacheData.setPropType(writeBackPropertyType);
+ cacheData.setCoreIndex(reference->d()->property);
QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
bindingFunction->initBindingLocation();
- QQmlBinding *newBinding = new QQmlBinding(value, reference->d()->object, context);
- newBinding->setTarget(reference->d()->object, cacheData);
+ QQmlBinding *newBinding = QQmlBinding::create(&cacheData, value, reference->d()->object, context);
+ newBinding->setTarget(reference->d()->object, cacheData, pd);
QQmlPropertyPrivate::setBinding(newBinding);
return;
} else {
- QQmlPropertyPrivate::removeBinding(reference->d()->object, QQmlPropertyData::encodeValueTypePropertyIndex(reference->d()->property, pd->coreIndex));
-
+ QQmlPropertyPrivate::removeBinding(reference->d()->object, QQmlPropertyIndex(reference->d()->property, pd->coreIndex()));
}
}
+ QMetaProperty property = metaObject->property(pd->coreIndex());
+ Q_ASSERT(property.isValid());
QVariant v = v4->toVariant(value, property.userType());
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index 5f9fa69944..01c4f476d6 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -39,7 +39,6 @@
#include "qqmlvme_p.h"
-#include "qqmlcompiler_p.h"
#include "qqmlboundsignal_p.h"
#include "qqmlstringconverters_p.h"
#include <private/qmetaobjectbuilder_p.h>
diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h
index ac9db5c046..99d63380ad 100644
--- a/src/qml/qml/qqmlvme_p.h
+++ b/src/qml/qml/qqmlvme_p.h
@@ -69,7 +69,6 @@ QT_BEGIN_NAMESPACE
class QObject;
class QJSValue;
class QQmlScriptData;
-class QQmlCompiledData;
class QQmlContextData;
namespace QQmlVMETypes {
@@ -84,10 +83,9 @@ namespace QQmlVMETypes {
struct State {
enum Flag { Deferred = 0x00000001 };
- State() : flags(0), context(0), compiledData(0), instructionStream(0) {}
+ State() : flags(0), context(0), instructionStream(0) {}
quint32 flags;
QQmlContextData *context;
- QQmlCompiledData *compiledData;
const char *instructionStream;
QBitField bindingSkipList;
};
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 8697a291e2..4f13b44fc0 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -159,14 +159,13 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
QQmlData *targetDData = QQmlData::get(target, /*create*/false);
if (!targetDData)
return;
- int coreIndex;
- QQmlPropertyData::decodeValueTypePropertyIndex(aliasData->encodedMetaPropertyIndex, &coreIndex);
+ int coreIndex = QQmlPropertyIndex::fromEncoded(aliasData->encodedMetaPropertyIndex).coreIndex();
const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex);
if (!pd)
return;
- if (pd->notifyIndex != -1)
- connect(target, pd->notifyIndex, ctxt->engine);
+ if (pd->notifyIndex() != -1)
+ connect(target, pd->notifyIndex(), ctxt->engine);
}
metaObject.setFlag();
@@ -199,10 +198,9 @@ QQmlInterceptorMetaObject::~QQmlInterceptorMetaObject()
}
-void QQmlInterceptorMetaObject::registerInterceptor(int index, int valueIndex, QQmlPropertyValueInterceptor *interceptor)
+void QQmlInterceptorMetaObject::registerInterceptor(QQmlPropertyIndex index, QQmlPropertyValueInterceptor *interceptor)
{
- interceptor->m_coreIndex = index;
- interceptor->m_valueTypeCoreIndex = valueIndex;
+ interceptor->m_propertyIndex = index;
interceptor->m_next = interceptors;
interceptors = interceptor;
}
@@ -220,14 +218,14 @@ int QQmlInterceptorMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id,
bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a)
{
if (c == QMetaObject::WriteProperty && interceptors &&
- !(*reinterpret_cast<int*>(a[3]) & QQmlPropertyPrivate::BypassInterceptor)) {
+ !(*reinterpret_cast<int*>(a[3]) & QQmlPropertyData::BypassInterceptor)) {
for (QQmlPropertyValueInterceptor *vi = interceptors; vi; vi = vi->m_next) {
- if (vi->m_coreIndex != id)
+ if (vi->m_propertyIndex.coreIndex() != id)
continue;
- int valueIndex = vi->m_valueTypeCoreIndex;
- int type = QQmlData::get(object)->propertyCache->property(id)->propType;
+ const int valueIndex = vi->m_propertyIndex.valueTypeIndex();
+ int type = QQmlData::get(object)->propertyCache->property(id)->propType();
if (type != QVariant::Invalid) {
if (valueIndex != -1) {
@@ -278,7 +276,7 @@ bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a)
bool updated = false;
if (newComponentValue != prevComponentValue) {
valueProp.write(valueType, prevComponentValue);
- valueType->write(object, id, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+ valueType->write(object, id, QQmlPropertyData::DontRemoveBinding | QQmlPropertyData::BypassInterceptor);
vi->write(newComponentValue);
updated = true;
@@ -319,8 +317,6 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
ctxt(QQmlData::get(obj, true)->outerContext),
aliasEndpoints(0), compilationUnit(qmlCompilationUnit), compiledObject(0)
{
- cache->addref();
-
QQmlData::get(obj)->hasVMEMetaObject = true;
if (compilationUnit && qmlObjectId >= 0) {
@@ -345,8 +341,6 @@ QQmlVMEMetaObject::~QQmlVMEMetaObject()
delete [] aliasEndpoints;
qDeleteAll(varObjectGuards);
-
- cache->release();
}
QV4::MemberData *QQmlVMEMetaObject::propertyAndMethodStorageAsMemberData()
@@ -614,6 +608,9 @@ QRectF QQmlVMEMetaObject::readPropertyAsRectF(int id)
return v->d()->data.value<QRectF>();
}
+#if defined(Q_OS_WINRT) && defined(_M_ARM)
+#pragma optimize("", off)
+#endif
int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void **a)
{
Q_ASSERT(o == object);
@@ -634,7 +631,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
id -= propOffset();
if (id < propertyCount) {
- const QV4::CompiledData::Property::Type t = static_cast<QV4::CompiledData::Property::Type>(compiledObject->propertyTable()[id].type);
+ const QV4::CompiledData::Property::Type t = static_cast<QV4::CompiledData::Property::Type>(qint32(compiledObject->propertyTable()[id].type));
bool needActivate = false;
if (t == QV4::CompiledData::Property::Var) {
@@ -849,6 +846,9 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
if (!ctxt) return -1;
+ while (aliasData->aliasToLocalAlias)
+ aliasData = &compiledObject->aliasTable()[aliasData->localAliasIndex];
+
QQmlContext *context = ctxt->asQQmlContext();
QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(context);
@@ -867,16 +867,17 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
if (!targetDData)
return -1;
- int coreIndex;
- const int valueTypePropertyIndex = QQmlPropertyData::decodeValueTypePropertyIndex(aliasData->encodedMetaPropertyIndex, &coreIndex);
+ QQmlPropertyIndex encodedIndex = QQmlPropertyIndex::fromEncoded(aliasData->encodedMetaPropertyIndex);
+ int coreIndex = encodedIndex.coreIndex();
+ const int valueTypePropertyIndex = encodedIndex.valueTypeIndex();
// Remove binding (if any) on write
if(c == QMetaObject::WriteProperty) {
int flags = *reinterpret_cast<int*>(a[3]);
- if (flags & QQmlPropertyPrivate::RemoveBindingOnAliasWrite) {
+ if (flags & QQmlPropertyData::RemoveBindingOnAliasWrite) {
QQmlData *targetData = QQmlData::get(target);
if (targetData && targetData->hasBindingBit(coreIndex))
- QQmlPropertyPrivate::removeBinding(target, aliasData->encodedMetaPropertyIndex);
+ QQmlPropertyPrivate::removeBinding(target, encodedIndex);
}
}
@@ -885,7 +886,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
return -1;
const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex);
// Value type property
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(pd->propType);
+ QQmlValueType *valueType = QQmlValueTypeFactory::valueType(pd->propType());
Q_ASSERT(valueType);
valueType->read(target, coreIndex);
@@ -934,10 +935,10 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
// are not rewritten correctly but this bug is deemed out-of-scope to fix for
// performance reasons; see QTBUG-24064) and thus compilation will have failed.
QQmlError e;
- e.setDescription(QString::fromLatin1("Exception occurred during compilation of "
- "function: %1")
- .arg(QString::fromUtf8(QMetaObject::method(_id)
- .methodSignature())));
+ e.setDescription(QLatin1String("Exception occurred during compilation of "
+ "function: ")
+ + QString::fromUtf8(QMetaObject::method(_id)
+ .methodSignature()));
ep->warning(e);
return -1; // The dynamic method with that id is not available.
}
@@ -949,15 +950,14 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
for (uint ii = 0; ii < parameterCount; ++ii)
callData->args[ii] = scope.engine->fromVariant(*(QVariant *)a[ii + 1]);
- QV4::ScopedValue result(scope);
- result = function->call(callData);
+ function->call(scope, callData);
if (scope.hasException()) {
QQmlError error = scope.engine->catchExceptionAsQmlError();
if (error.isValid())
ep->warning(error);
if (a[0]) *(QVariant *)a[0] = QVariant();
} else {
- if (a[0]) *(QVariant *)a[0] = scope.engine->toVariant(result, 0);
+ if (a[0]) *(QVariant *)a[0] = scope.engine->toVariant(scope.result, 0);
}
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
@@ -972,6 +972,9 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
else
return object->qt_metacall(c, _id, a);
}
+#if defined(Q_OS_WINRT) && defined(_M_ARM)
+#pragma optimize("", on)
+#endif
QV4::ReturnedValue QQmlVMEMetaObject::method(int index)
{
@@ -1191,8 +1194,11 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex,
if (!*target)
return false;
- if (!aliasData->isObjectAlias())
- *valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(aliasData->encodedMetaPropertyIndex, coreIndex);
+ if (!aliasData->isObjectAlias()) {
+ QQmlPropertyIndex encodedIndex = QQmlPropertyIndex::fromEncoded(aliasData->encodedMetaPropertyIndex);
+ *coreIndex = encodedIndex.coreIndex();
+ *valueTypeIndex = encodedIndex.valueTypeIndex();
+ }
return true;
}
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index 75e7ed6cb1..031bfdfb9b 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -64,13 +64,15 @@
#include <private/qobject_p.h>
#include "qqmlguard_p.h"
-#include "qqmlcompiler_p.h"
#include "qqmlcontext_p.h"
+#include "qqmlpropertycache_p.h"
#include <private/qv8engine_p.h>
#include <private/qflagpointer_p.h>
+#include <private/qv4object_p.h>
#include <private/qv4value_p.h>
+#include <private/qqmlpropertyvalueinterceptor_p.h>
QT_BEGIN_NAMESPACE
@@ -95,7 +97,7 @@ public:
QQmlInterceptorMetaObject(QObject *obj, QQmlPropertyCache *cache);
~QQmlInterceptorMetaObject();
- void registerInterceptor(int index, int valueIndex, QQmlPropertyValueInterceptor *interceptor);
+ void registerInterceptor(QQmlPropertyIndex index, QQmlPropertyValueInterceptor *interceptor);
static QQmlInterceptorMetaObject *get(QObject *obj);
@@ -104,13 +106,22 @@ public:
// Used by auto-tests for inspection
QQmlPropertyCache *propertyCache() const { return cache; }
+ bool intercepts(QQmlPropertyIndex propertyIndex) const
+ {
+ for (auto it = interceptors; it; it = it->m_next) {
+ if (it->m_propertyIndex == propertyIndex)
+ return true;
+ }
+ return false;
+ }
+
protected:
int metaCall(QObject *o, QMetaObject::Call c, int id, void **a) Q_DECL_OVERRIDE;
bool intercept(QMetaObject::Call c, int id, void **a);
public:
QObject *object;
- QQmlPropertyCache *cache;
+ QQmlRefPointer<QQmlPropertyCache> cache;
QBiPointer<QDynamicMetaObjectData, const QMetaObject> parent;
QQmlPropertyValueInterceptor *interceptors;
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index e9644839d1..dd517374a5 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -502,7 +502,7 @@ ReturnedValue NodePrototype::method_get_firstChild(CallContext *ctx)
if (r->d()->d->children.isEmpty())
return Encode::null();
else
- return Node::create(scope.engine, r->d()->d->children.first());
+ return Node::create(scope.engine, r->d()->d->children.constFirst());
}
ReturnedValue NodePrototype::method_get_lastChild(CallContext *ctx)
@@ -515,7 +515,7 @@ ReturnedValue NodePrototype::method_get_lastChild(CallContext *ctx)
if (r->d()->d->children.isEmpty())
return Encode::null();
else
- return Node::create(scope.engine, r->d()->d->children.last());
+ return Node::create(scope.engine, r->d()->d->children.constLast());
}
ReturnedValue NodePrototype::method_get_previousSibling(CallContext *ctx)
@@ -715,7 +715,7 @@ ReturnedValue Text::method_isElementContentWhitespace(CallContext *ctx)
Scoped<Node> r(scope, ctx->thisObject().as<Node>());
if (!r) return Encode::undefined();
- return Encode(r->d()->d->data.trimmed().isEmpty());
+ return Encode(QStringRef(&r->d()->d->data).trimmed().isEmpty());
}
ReturnedValue Text::method_wholeText(CallContext *ctx)
@@ -817,7 +817,8 @@ ReturnedValue Document::load(ExecutionEngine *v4, const QByteArray &data)
}
nodeStack.append(node);
- foreach (const QXmlStreamAttribute &a, reader.attributes()) {
+ const auto attributes = reader.attributes();
+ for (const QXmlStreamAttribute &a : attributes) {
NodeImpl *attr = new NodeImpl;
attr->document = document;
attr->type = NodeImpl::Attr;
@@ -1016,8 +1017,8 @@ public:
ReturnedValue abort(Object *thisObject, QQmlContextData *context);
void addHeader(const QString &, const QString &);
- QString header(const QString &name);
- QString headers();
+ QString header(const QString &name) const;
+ QString headers() const;
QString responseBody();
const QByteArray & rawResponseBody() const;
@@ -1144,36 +1145,37 @@ void QQmlXMLHttpRequest::addHeader(const QString &name, const QString &value)
}
}
-QString QQmlXMLHttpRequest::header(const QString &name)
+QString QQmlXMLHttpRequest::header(const QString &name) const
{
- QByteArray utfname = name.toLower().toUtf8();
-
- foreach (const HeaderPair &header, m_headersList) {
- if (header.first == utfname)
- return QString::fromUtf8(header.second);
+ if (!m_headersList.isEmpty()) {
+ const QByteArray utfname = name.toLower().toUtf8();
+ for (const HeaderPair &header : m_headersList) {
+ if (header.first == utfname)
+ return QString::fromUtf8(header.second);
+ }
}
return QString();
}
-QString QQmlXMLHttpRequest::headers()
+QString QQmlXMLHttpRequest::headers() const
{
QString ret;
- foreach (const HeaderPair &header, m_headersList) {
+ for (const HeaderPair &header : m_headersList) {
if (ret.length())
ret.append(QLatin1String("\r\n"));
- ret = ret % QString::fromUtf8(header.first) % QLatin1String(": ")
- % QString::fromUtf8(header.second);
+ ret += QString::fromUtf8(header.first) + QLatin1String(": ")
+ + QString::fromUtf8(header.second);
}
return ret;
}
void QQmlXMLHttpRequest::fillHeadersList()
{
- QList<QByteArray> headerList = m_network->rawHeaderList();
+ const QList<QByteArray> headerList = m_network->rawHeaderList();
m_headersList.clear();
- foreach (const QByteArray &header, headerList) {
+ for (const QByteArray &header : headerList) {
HeaderPair pair (header.toLower(), m_network->rawHeader(header));
if (pair.first == "set-cookie" ||
pair.first == "set-cookie2")
@@ -1235,7 +1237,8 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url)
} else if (m_method == QLatin1String("DELETE")) {
m_network = networkAccessManager()->deleteResource(request);
} else if ((m_method == QLatin1String("OPTIONS")) ||
- m_method == QLatin1String("PROPFIND")) {
+ m_method == QLatin1String("PROPFIND") ||
+ m_method == QLatin1String("PATCH")) {
QBuffer *buffer = new QBuffer;
buffer->setData(m_data);
buffer->open(QIODevice::ReadOnly);
@@ -1430,7 +1433,7 @@ void QQmlXMLHttpRequest::finished()
void QQmlXMLHttpRequest::readEncoding()
{
- foreach (const HeaderPair &header, m_headersList) {
+ for (const HeaderPair &header : qAsConst(m_headersList)) {
if (header.first == "content-type") {
int separatorIdx = header.second.indexOf(';');
if (separatorIdx == -1) {
@@ -1559,7 +1562,7 @@ void QQmlXMLHttpRequest::dispatchCallback(Object *thisObj, QQmlContextData *cont
QV4::ScopedCallData callData(scope);
callData->thisObject = Encode::undefined();
- callback->call(callData);
+ callback->call(scope, callData);
if (scope.engine->hasException) {
QQmlError error = scope.engine->catchExceptionAsQmlError();
@@ -1620,22 +1623,23 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
c->proto->mark(e);
FunctionObject::markObjects(that, e);
}
- static ReturnedValue construct(const Managed *that, QV4::CallData *)
+ static void construct(const Managed *that, Scope &scope, QV4::CallData *)
{
- Scope scope(static_cast<const QQmlXMLHttpRequestCtor *>(that)->engine());
Scoped<QQmlXMLHttpRequestCtor> ctor(scope, that->as<QQmlXMLHttpRequestCtor>());
- if (!ctor)
- return scope.engine->throwTypeError();
+ if (!ctor) {
+ scope.result = scope.engine->throwTypeError();
+ return;
+ }
QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->v8Engine->networkAccessManager());
Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocObject<QQmlXMLHttpRequestWrapper>(r));
ScopedObject proto(scope, ctor->d()->proto);
w->setPrototype(proto);
- return w.asReturnedValue();
+ scope.result = w.asReturnedValue();
}
- static ReturnedValue call(const Managed *, QV4::CallData *) {
- return Primitive::undefinedValue().asReturnedValue();
+ static void call(const Managed *, Scope &scope, QV4::CallData *) {
+ scope.result = Primitive::undefinedValue();
}
void setupProto();
@@ -1735,7 +1739,8 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
method != QLatin1String("POST") &&
method != QLatin1String("DELETE") &&
method != QLatin1String("OPTIONS") &&
- method != QLatin1String("PROPFIND"))
+ method != QLatin1String("PROPFIND") &&
+ method != QLatin1String("PATCH"))
V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Unsupported HTTP method type");
// Argument 1 - URL
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 54c29b4b8a..222b61ae49 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -42,6 +42,7 @@
#include <QtQml/qqmlcomponent.h>
#include <private/qqmlengine_p.h>
#include <private/qqmlcomponent_p.h>
+#include <private/qqmlloggingcategory_p.h>
#include <private/qqmlstringconverters_p.h>
#include <private/qqmllocale_p.h>
#include <private/qv8engine_p.h>
@@ -76,6 +77,8 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qloggingcategory.h>
+#include <QDebug>
+
QT_BEGIN_NAMESPACE
using namespace QV4;
@@ -137,6 +140,7 @@ Heap::QtObject::QtObject(QQmlEngine *qmlEngine)
o->defineDefaultProperty(QStringLiteral("darker"), QV4::QtObject::method_darker);
o->defineDefaultProperty(QStringLiteral("tint"), QV4::QtObject::method_tint);
o->defineDefaultProperty(QStringLiteral("quit"), QV4::QtObject::method_quit);
+ o->defineDefaultProperty(QStringLiteral("exit"), QV4::QtObject::method_exit);
o->defineDefaultProperty(QStringLiteral("createQmlObject"), QV4::QtObject::method_createQmlObject);
o->defineDefaultProperty(QStringLiteral("createComponent"), QV4::QtObject::method_createComponent);
}
@@ -992,6 +996,8 @@ This function causes the QQmlEngine::quit() signal to be emitted.
Within the \l {Prototyping with qmlscene}, this causes the launcher application to exit;
to quit a C++ application when this method is called, connect the
QQmlEngine::quit() signal to the QCoreApplication::quit() slot.
+
+\sa exit()
*/
ReturnedValue QtObject::method_quit(CallContext *ctx)
{
@@ -1000,6 +1006,28 @@ ReturnedValue QtObject::method_quit(CallContext *ctx)
}
/*!
+ \qmlmethod Qt::exit(int retCode)
+
+ This function causes the QQmlEngine::exit(int) signal to be emitted.
+ Within the \l {Prototyping with qmlscene}, this causes the launcher application to exit
+ the specified return code. To exit from the event loop with a specified return code when this
+ method is called, a C++ application can connect the QQmlEngine::exit(int) signal
+ to the QCoreApplication::exit(int) slot.
+
+ \sa quit()
+*/
+ReturnedValue QtObject::method_exit(CallContext *ctx)
+{
+ if (ctx->argc() != 1)
+ V4THROW_ERROR("Qt.exit(): Invalid arguments");
+
+ int retCode = ctx->args()[0].toNumber();
+
+ QQmlEnginePrivate::get(ctx->engine()->qmlEngine())->sendExit(retCode);
+ return QV4::Encode::undefined();
+}
+
+/*!
\qmlmethod object Qt::createQmlObject(string qml, object parent, string filepath)
Returns a new object created from the given \a string of QML which will have the specified \a parent,
@@ -1032,7 +1060,9 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
struct Error {
static ReturnedValue create(QV4::ExecutionEngine *v4, const QList<QQmlError> &errors) {
Scope scope(v4);
- QString errorstr = QLatin1String("Qt.createQmlObject(): failed to create object: ");
+ QString errorstr;
+ // '+=' reserves extra capacity. Follow-up appending will be probably free.
+ errorstr += QLatin1String("Qt.createQmlObject(): failed to create object: ");
QV4::ScopedArrayObject qmlerrors(scope, v4->newArrayObject());
QV4::ScopedObject qmlerror(scope);
@@ -1274,8 +1304,8 @@ ReturnedValue QtObject::method_locale(CallContext *ctx)
Heap::QQmlBindingFunction::QQmlBindingFunction(const QV4::FunctionObject *originalFunction)
: QV4::Heap::FunctionObject(originalFunction->scope(), originalFunction->name())
- , originalFunction(originalFunction->d())
{
+ this->originalFunction = originalFunction->d();
}
void QQmlBindingFunction::initBindingLocation()
@@ -1285,11 +1315,10 @@ void QQmlBindingFunction::initBindingLocation()
d()->bindingLocation.line = frame.line;
}
-ReturnedValue QQmlBindingFunction::call(const Managed *that, CallData *callData)
+void QQmlBindingFunction::call(const Managed *that, Scope &scope, CallData *callData)
{
- Scope scope(static_cast<const QQmlBindingFunction*>(that)->engine());
ScopedFunctionObject function(scope, static_cast<const QQmlBindingFunction*>(that)->d()->originalFunction);
- return function->call(callData);
+ function->call(scope, callData);
}
void QQmlBindingFunction::markObjects(Heap::Base *that, ExecutionEngine *e)
@@ -1465,28 +1494,42 @@ static QString jsStack(QV4::ExecutionEngine *engine) {
static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *ctx,
bool printStack = false)
{
+ QLoggingCategory *loggingCategory = 0;
QString result;
QV4::ExecutionEngine *v4 = ctx->d()->engine;
- for (int i = 0; i < ctx->argc(); ++i) {
- if (i != 0)
+ int start = 0;
+ if (ctx->argc() > 0) {
+ if (const QObjectWrapper* wrapper = ctx->args()[0].as<QObjectWrapper>()) {
+ if (QQmlLoggingCategory* category = qobject_cast<QQmlLoggingCategory*>(wrapper->object())) {
+ if (category->category())
+ loggingCategory = category->category();
+ else
+ V4THROW_ERROR("A QmlLoggingCatgory was provided without a valid name");
+ start = 1;
+ }
+ }
+ }
+
+
+ for (int i = start; i < ctx->argc(); ++i) {
+ if (i != start)
result.append(QLatin1Char(' '));
if (ctx->args()[i].as<ArrayObject>())
- result.append(QLatin1Char('[') + ctx->args()[i].toQStringNoThrow() + QLatin1Char(']'));
+ result += QLatin1Char('[') + ctx->args()[i].toQStringNoThrow() + QLatin1Char(']');
else
result.append(ctx->args()[i].toQStringNoThrow());
}
- if (printStack) {
- result.append(QLatin1Char('\n'));
- result.append(jsStack(v4));
- }
+ if (printStack)
+ result += QLatin1Char('\n') + jsStack(v4);
static QLoggingCategory qmlLoggingCategory("qml");
static QLoggingCategory jsLoggingCategory("js");
- QLoggingCategory *loggingCategory = v4->qmlEngine() ? &qmlLoggingCategory : &jsLoggingCategory;
+ if (!loggingCategory)
+ loggingCategory = v4->qmlEngine() ? &qmlLoggingCategory : &jsLoggingCategory;
QV4::StackFrame frame = v4->currentStackFrame();
const QByteArray baSource = frame.source.toUtf8();
const QByteArray baFunction = frame.function.toUtf8();
@@ -2001,18 +2044,19 @@ ReturnedValue GlobalExtensions::method_string_arg(CallContext *ctx)
/*!
\qmlmethod Qt::callLater(function)
\qmlmethod Qt::callLater(function, argument1, argument2, ...)
+\since 5.8
Use this function to eliminate redundant calls to a function or signal.
-The function passed as the first argument to \l{QML:Qt::callLater()}{Qt.callLater()}
+The function passed as the first argument to Qt.callLater()
will be called later, once the QML engine returns to the event loop.
When this function is called multiple times in quick succession with the
same function as its first argument, that function will be called only once.
For example:
-\snippet doc/src/snippets/qml/qtLater.qml 0
+\snippet qml/qtLater.qml 0
-Any additional arguments passed to \l{QML:Qt::callLater()}{Qt.callLater()} will
+Any additional arguments passed to Qt.callLater() will
be passed on to the function invoked. Note that if redundant calls
are eliminated, then only the last set of arguments will be passed to the
function.
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index 5404ab3616..8c0759679a 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -122,6 +122,7 @@ struct QtObject : Object
static ReturnedValue method_btoa(CallContext *ctx);
static ReturnedValue method_atob(CallContext *ctx);
static ReturnedValue method_quit(CallContext *ctx);
+ static ReturnedValue method_exit(CallContext *ctx);
static ReturnedValue method_resolvedUrl(CallContext *ctx);
static ReturnedValue method_createQmlObject(CallContext *ctx);
static ReturnedValue method_createComponent(CallContext *ctx);
@@ -188,7 +189,7 @@ struct QQmlBindingFunction : public QV4::FunctionObject
void initBindingLocation(); // from caller stack trace
- static ReturnedValue call(const Managed *that, CallData *callData);
+ static void call(const Managed *that, Scope &scope, CallData *callData);
static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index e08ff3b979..f15020f6c9 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -160,10 +160,9 @@ QV8Engine::~QV8Engine()
qDeleteAll(m_extensionData);
m_extensionData.clear();
-#if !defined(QT_NO_XMLSTREAMREADER) && defined(QT_NO_NETWORK)
qt_rem_qmlxmlhttprequest(m_v4Engine, m_xmlHttpRequestData);
m_xmlHttpRequestData = 0;
-#endif
+
delete m_listModelData;
m_listModelData = 0;