aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2012-05-11 12:01:41 +0100
committerQt by Nokia <qt-info@nokia.com>2012-05-24 12:52:43 +0200
commitd2e557c2c2d7fcf3bf7c1676df3902e115986dc2 (patch)
tree65f47e443efa9635a2634880c01dc439817f9566
parent0a3ff88f851771e52d119fab90c0254de6950585 (diff)
Lazily create QMetaObjects
For internal QML built types, creating a metaobject each time is just wasteful. Additionally, as the property caches were always created from the intermediate QMetaObject, it was difficult to pass information directly from the compiler to the property cache. Change-Id: I769526b0edaaf16a86883f3065b75618b94e4077 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro2
-rw-r--r--src/qml/qml/ftw/ftw.pri2
-rw-r--r--src/qml/qml/ftw/qfastmetabuilder.cpp343
-rw-r--r--src/qml/qml/ftw/qfastmetabuilder_p.h234
-rw-r--r--src/qml/qml/ftw/qhashedstring_p.h9
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp23
-rw-r--r--src/qml/qml/qqmlboundsignal_p.h2
-rw-r--r--src/qml/qml/qqmlcompileddata.cpp31
-rw-r--r--src/qml/qml/qqmlcompiler.cpp1049
-rw-r--r--src/qml/qml/qqmlcompiler_p.h20
-rw-r--r--src/qml/qml/qqmlengine.cpp97
-rw-r--r--src/qml/qml/qqmlengine_p.h17
-rw-r--r--src/qml/qml/qqmlglobal_p.h96
-rw-r--r--src/qml/qml/qqmlinstruction.cpp2
-rw-r--r--src/qml/qml/qqmlinstruction_p.h1
-rw-r--r--src/qml/qml/qqmllist.cpp6
-rw-r--r--src/qml/qml/qqmllist_p.h3
-rw-r--r--src/qml/qml/qqmlproperty.cpp184
-rw-r--r--src/qml/qml/qqmlproperty_p.h11
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp530
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h212
-rw-r--r--src/qml/qml/qqmlscript.cpp27
-rw-r--r--src/qml/qml/qqmlscript_p.h21
-rw-r--r--src/qml/qml/qqmltypeloader.cpp14
-rw-r--r--src/qml/qml/qqmltypeloader_p.h16
-rw-r--r--src/qml/qml/qqmlvme.cpp22
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp167
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h37
-rw-r--r--src/qml/qml/v4/qv4bindings.cpp23
-rw-r--r--src/qml/qml/v4/qv4compiler.cpp2
-rw-r--r--src/qml/qml/v4/qv4ir.cpp8
-rw-r--r--src/qml/qml/v4/qv4ir_p.h11
-rw-r--r--src/qml/qml/v4/qv4irbuilder.cpp46
-rw-r--r--src/qml/qml/v8/qv8qobjectwrapper.cpp33
-rw-r--r--src/quick/items/qquickborderimage.cpp3
-rw-r--r--src/quick/items/qquickborderimage_p_p.h3
-rw-r--r--src/quick/items/qquickflickable.cpp6
-rw-r--r--src/quick/items/qquickitem.cpp21
-rw-r--r--src/quick/items/qquickitemsmodule.cpp4
-rw-r--r--src/quick/items/qquickloader.cpp4
-rw-r--r--src/quick/items/qquickpathview.cpp32
-rw-r--r--src/quick/items/qquicktext.cpp3
-rw-r--r--src/quick/items/qquicktextedit.cpp26
-rw-r--r--src/quick/items/qquickvisualadaptormodel.cpp40
-rw-r--r--src/quick/items/qquickvisualdatamodel.cpp28
-rw-r--r--src/quick/util/qquickanimation.cpp4
-rw-r--r--src/quick/util/qquickconnections.cpp2
-rw-r--r--tests/auto/qml/qqmlcpputils/qqmlcpputils.pro2
-rw-r--r--tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/secondAlias.qml15
-rw-r--r--tests/auto/qml/qqmlecmascript/data/varAlias.qml9
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp21
-rw-r--r--tests/auto/qml/qqmlglobal/qqmlglobal.pro2
-rw-r--r--tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp3
-rw-r--r--tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp2
-rw-r--r--tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp1
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp2
-rw-r--r--tests/auto/qmltest/buttonclick/tst_buttonclick.qml2
58 files changed, 1842 insertions, 1700 deletions
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
index fdd1f6e05f..ed4d6b4992 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
+++ b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
@@ -1,7 +1,7 @@
load(qt_module)
TARGET = qmldbg_tcp
-QT += qml-private network
+QT += qml-private network v8-private core-private
load(qt_plugin)
diff --git a/src/qml/qml/ftw/ftw.pri b/src/qml/qml/ftw/ftw.pri
index f2fec4e2dd..c2409c6790 100644
--- a/src/qml/qml/ftw/ftw.pri
+++ b/src/qml/qml/ftw/ftw.pri
@@ -6,7 +6,6 @@ HEADERS += \
$$PWD/qqmlrefcount_p.h \
$$PWD/qqmlpool_p.h \
$$PWD/qfieldlist_p.h \
- $$PWD/qfastmetabuilder_p.h \
$$PWD/qhashfield_p.h \
$$PWD/qqmlthread_p.h \
$$PWD/qfinitestack_p.h \
@@ -22,7 +21,6 @@ SOURCES += \
$$PWD/qintrusivelist.cpp \
$$PWD/qhashedstring.cpp \
$$PWD/qqmlpool.cpp \
- $$PWD/qfastmetabuilder.cpp \
$$PWD/qqmlthread.cpp \
$$PWD/qqmltrace.cpp \
diff --git a/src/qml/qml/ftw/qfastmetabuilder.cpp b/src/qml/qml/ftw/qfastmetabuilder.cpp
deleted file mode 100644
index b22be84107..0000000000
--- a/src/qml/qml/ftw/qfastmetabuilder.cpp
+++ /dev/null
@@ -1,343 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qfastmetabuilder_p.h"
-
-#include <QtCore/qmetaobject.h>
-#include <private/qobject_p.h>
-#include <private/qmetaobject_p.h>
-
-QT_BEGIN_NAMESPACE
-
-struct QFastMetaBuilderHeader
-{
- int fieldCount;
-};
-
-#define FMBHEADER_FIELD_COUNT 1
-
-#define HEADER_FIELD_COUNT 14
-#define CLASSINFO_FIELD_COUNT 2
-#define METHOD_FIELD_COUNT 5
-#define PROPERTY_FIELD_COUNT 3
-#define PROPERTY_NOTIFY_FIELD_COUNT 1
-
-static inline uint *fieldPointer(QByteArray &data)
-{ return reinterpret_cast<uint *>(data.data()) + FMBHEADER_FIELD_COUNT; }
-
-static inline const uint *fieldPointer(const QByteArray &data)
-{ return reinterpret_cast<const uint *>(data.constData()) + FMBHEADER_FIELD_COUNT; }
-
-static inline QMetaObjectPrivate *priv(QByteArray &data)
-{ return reinterpret_cast<QMetaObjectPrivate*>(fieldPointer(data)); }
-
-static inline const QMetaObjectPrivate *priv(const QByteArray &data)
-{ return reinterpret_cast<const QMetaObjectPrivate*>(fieldPointer(data)); }
-
-static inline QFastMetaBuilderHeader *header(QByteArray &data)
-{ return reinterpret_cast<QFastMetaBuilderHeader*>(data.data()); }
-
-static inline const QFastMetaBuilderHeader *header(const QByteArray &data)
-{ return reinterpret_cast<const QFastMetaBuilderHeader*>(data.constData()); }
-
-QFastMetaBuilder::QFastMetaBuilder()
- : m_stringData(0), m_stringCount(0), m_stringDataLength(0),
- m_stringCountAllocated(0), m_stringCountLoaded(0)
-{
-}
-
-QFastMetaBuilder::~QFastMetaBuilder()
-{
-}
-
-QFastMetaBuilder::StringRef QFastMetaBuilder::init(int classNameLength,
- int propertyCount, int methodCount,
- int signalCount, int classInfoCount,
- int paramDataSize, int *paramIndex)
-{
- Q_ASSERT(m_data.isEmpty());
- Q_ASSERT(classNameLength > 0);
- Q_ASSERT(propertyCount >= 0);
- Q_ASSERT(methodCount >= 0);
- Q_ASSERT(signalCount >= 0);
- Q_ASSERT(classInfoCount >= 0);
- Q_ASSERT(paramDataSize >= 0);
- Q_ASSERT((paramIndex != 0) || (methodCount + signalCount == 0));
-
- int fieldCount = FMBHEADER_FIELD_COUNT +
- HEADER_FIELD_COUNT +
- propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT) +
- methodCount * (METHOD_FIELD_COUNT) +
- signalCount * (METHOD_FIELD_COUNT) +
- paramDataSize +
- classInfoCount * CLASSINFO_FIELD_COUNT;
- // Ensure stringdata alignment (void*)
- fieldCount += fieldCount % (sizeof(void*) / sizeof(uint));
-
- m_stringCount = 2; // class name and zero string
- m_stringDataLength = classNameLength + 1;
- m_data.resize(fieldCount * sizeof(uint) + m_stringCount * sizeof(QByteArrayData) + m_stringDataLength);
- m_stringCountAllocated = m_stringCount;
- m_stringData = reinterpret_cast<QByteArrayData *>(m_data.data() + fieldCount * sizeof(uint));
-
- m_zeroString._b = this;
- m_zeroString._i = 1;
- m_zeroString._o = classNameLength;
- m_zeroString._l = 0;
-
- header(m_data)->fieldCount = fieldCount;
-
- QMetaObjectPrivate *p = priv(m_data);
-
- int dataIndex = HEADER_FIELD_COUNT;
-
- p->revision = 7;
- p->className = 0;
-
- // Class infos
- p->classInfoCount = classInfoCount;
- if (p->classInfoCount) {
- p->classInfoData = dataIndex;
- dataIndex += p->classInfoCount * CLASSINFO_FIELD_COUNT;
- } else {
- p->classInfoData = 0;
- }
-
- // Methods
- p->methodCount = methodCount + signalCount;
- if (p->methodCount) {
- p->methodData = dataIndex;
- dataIndex += p->methodCount * METHOD_FIELD_COUNT;
- *paramIndex = dataIndex;
- dataIndex += paramDataSize;
- } else {
- p->methodData = 0;
- }
- p->signalCount = signalCount;
-
- // Properties
- p->propertyCount = propertyCount;
- if (p->propertyCount) {
- p->propertyData = dataIndex;
- dataIndex += p->propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT);
- } else {
- p->propertyData = 0;
- }
-
- // Flags
- p->flags = DynamicMetaObject; // Always dynamic
-
- // Enums and constructors not supported
- p->enumeratorCount = 0;
- p->enumeratorData = 0;
- p->constructorCount = 0;
- p->constructorData = 0;
-
- StringRef className;
- className._b = this;
- className._i = 0;
- className._o = 0;
- className._l = classNameLength;
- return className;
-}
-
-// Allocate a string of \a length. \a length should *not* include the null terminator.
-QFastMetaBuilder::StringRef QFastMetaBuilder::newString(int length)
-{
- Q_ASSERT(length > 0);
- Q_ASSERT_X(m_stringCountLoaded == 0, Q_FUNC_INFO,
- "All strings must be created before string loading begins");
-
- StringRef sr;
- sr._b = this;
- sr._i = m_stringCount;
- sr._o = m_stringDataLength;
- sr._l = length;
-
- ++m_stringCount;
- m_stringDataLength += length + 1 /* for null terminator */;
-
- return sr;
-}
-
-void QFastMetaBuilder::setClassInfo(int index, const StringRef &key, const StringRef &value)
-{
- Q_ASSERT(!m_data.isEmpty());
- Q_ASSERT(!key.isEmpty() && !value.isEmpty());
-
- QMetaObjectPrivate *p = priv(m_data);
- Q_ASSERT(index < p->classInfoCount);
-
- uint *ptr = fieldPointer(m_data) + p->classInfoData + index * CLASSINFO_FIELD_COUNT;
- // classinfo: key, value
- ptr[0] = key.index(); ptr[1] = value.index();
-}
-
-void QFastMetaBuilder::setProperty(int index, const StringRef &name, int type,
- PropertyFlag flags, int notifySignal)
-{
- Q_ASSERT(!m_data.isEmpty());
- Q_ASSERT(!name.isEmpty());
- Q_ASSERT(type != 0);
- Q_ASSERT(QMetaType::isRegistered(type));
-
- QMetaObjectPrivate *p = priv(m_data);
- Q_ASSERT(index < p->propertyCount);
-
- uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT;
- // properties: name, type, flags
- ptr[0] = name.index();
- ptr[1] = type;
- if (notifySignal == -1) {
- ptr[2] = flags | Scriptable | Readable;
- *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0;
- } else {
- ptr[2] = flags | Scriptable | Readable | Notify;
- *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal;
- }
-}
-
-void QFastMetaBuilder::setSignal(int index, const StringRef &name,
- int paramIndex, int argc, const int *types,
- const StringRef *parameterNames,
- QMetaType::Type type)
-{
- Q_ASSERT(!m_data.isEmpty());
- Q_ASSERT(!name.isEmpty());
- Q_ASSERT(QMetaType::isRegistered(type));
-
- QMetaObjectPrivate *p = priv(m_data);
- int mindex = metaObjectIndexForSignal(index);
-
- uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT;
- // methods: name, arc, parameters, tag, flags
- ptr[0] = name.index();
- ptr[1] = argc;
- ptr[2] = paramIndex;
- ptr[3] = m_zeroString.index();
- ptr[4] = AccessProtected | MethodSignal;
-
- uint *paramPtr = fieldPointer(m_data) + paramIndex;
- paramPtr[0] = type;
- if (argc) {
- Q_ASSERT(types != 0);
- Q_ASSERT(parameterNames != 0);
- for (int i = 0; i < argc; ++i) {
- Q_ASSERT(types[i] != 0);
- Q_ASSERT(QMetaType::isRegistered(types[i]));
- paramPtr[1+i] = types[i];
- paramPtr[1+argc+i] = parameterNames[i].index();
- }
- }
-}
-
-void QFastMetaBuilder::setMethod(int index, const StringRef &name,
- int paramIndex, int argc, const int *types,
- const StringRef *parameterNames,
- QMetaType::Type type)
-{
- Q_ASSERT(!m_data.isEmpty());
- Q_ASSERT(!name.isEmpty());
- Q_ASSERT(QMetaType::isRegistered(type));
-
- QMetaObjectPrivate *p = priv(m_data);
- int mindex = metaObjectIndexForMethod(index);
-
- uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT;
- // methods: name, arc, parameters, tag, flags
- ptr[0] = name.index();
- ptr[1] = argc;
- ptr[2] = paramIndex;
- ptr[3] = m_zeroString.index();
- ptr[4] = AccessProtected | MethodSlot;
-
- uint *paramPtr = fieldPointer(m_data) + paramIndex;
- paramPtr[0] = type;
- if (argc) {
- Q_ASSERT(types != 0);
- Q_ASSERT(parameterNames != 0);
- for (int i = 0; i < argc; ++i) {
- Q_ASSERT(types[i] != 0);
- Q_ASSERT(QMetaType::isRegistered(types[i]));
- paramPtr[1+i] = types[i];
- paramPtr[1+argc+i] = parameterNames[i].index();
- }
- }
-}
-
-int QFastMetaBuilder::metaObjectIndexForSignal(int index) const
-{
- Q_ASSERT(!m_data.isEmpty());
- Q_ASSERT(index < priv(m_data)->signalCount);
- return index;
-}
-
-int QFastMetaBuilder::metaObjectIndexForMethod(int index) const
-{
- Q_ASSERT(!m_data.isEmpty());
-
- const QMetaObjectPrivate *p = priv(m_data);
- Q_ASSERT(index < (p->methodCount - p->signalCount));
- return index + p->signalCount;
-}
-
-void QFastMetaBuilder::allocateStringData()
-{
- if (m_stringCountAllocated < m_stringCount) {
- m_data.resize(header(m_data)->fieldCount * sizeof(uint)
- + m_stringCount * sizeof(QByteArrayData) + m_stringDataLength);
- m_stringCountAllocated = m_stringCount;
- char *rawStringData = m_data.data() + header(m_data)->fieldCount * sizeof(uint);
- m_stringData = reinterpret_cast<QByteArrayData *>(rawStringData);
- }
-}
-
-void QFastMetaBuilder::fromData(QMetaObject *output, const QMetaObject *parent, const QByteArray &data)
-{
- output->d.superdata = parent;
- output->d.stringdata = reinterpret_cast<const QByteArrayData *>(data.constData() + header(data)->fieldCount * sizeof(uint));
- output->d.data = fieldPointer(data);
- output->d.extradata = 0;
- output->d.static_metacall = 0;
- output->d.relatedMetaObjects = 0;
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/qml/ftw/qfastmetabuilder_p.h b/src/qml/qml/ftw/qfastmetabuilder_p.h
deleted file mode 100644
index aebafc8b55..0000000000
--- a/src/qml/qml/ftw/qfastmetabuilder_p.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QFASTMETABUILDER_P_H
-#define QFASTMETABUILDER_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of moc. This header file may change from version to version without notice,
-// or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qglobal.h>
-#include <QtCore/qmetatype.h>
-#include <QtCore/qmetaobject.h>
-
-#include <private/qhashedstring_p.h>
-
-QT_BEGIN_NAMESPACE
-
-struct QMetaObject;
-class QFastMetaBuilder
-{
-public:
- QFastMetaBuilder();
- ~QFastMetaBuilder();
-
- struct StringRef {
- public:
- inline StringRef();
- inline StringRef(const StringRef &);
- inline StringRef &operator=(const StringRef &);
-
- inline void load(const QHashedStringRef &);
- inline void load(const QByteArray &);
- inline void load(const char *);
-
- inline bool isEmpty() const;
- inline QFastMetaBuilder *builder() const;
- inline int index() const;
- inline char *data();
- inline int length() const;
- inline void loadByteArrayData();
- private:
- friend class QFastMetaBuilder;
-
- QFastMetaBuilder *_b;
- int _i;
- int _o;
- int _l;
- };
- StringRef newString(int length);
-
- // Returns class name
- StringRef init(int classNameLength,
- int propertyCount, int methodCount,
- int signalCount, int classInfoCount,
- int paramDataSize, int *paramIndex);
-
- void setClassInfo(int index, const StringRef &key, const StringRef &value);
-
- enum PropertyFlag {
- None = 0x00000000,
- Writable = 0x00000002,
- Resettable = 0x00000004,
- Constant = 0x00000400,
- Final = 0x00000800
- };
- void setProperty(int index, const StringRef &name, int type,
- PropertyFlag flags, int notifySignal = -1);
- void setMethod(int index, const StringRef &name, int paramIndex, int argc = 0,
- const int *types = 0, const StringRef *parameterNames = 0,
- QMetaType::Type type = QMetaType::Void);
- void setSignal(int index, const StringRef &name, int paramIndex, int argc = 0,
- const int *types = 0, const StringRef *parameterNames = 0,
- QMetaType::Type type = QMetaType::Void);
-
- int metaObjectIndexForSignal(int) const;
- int metaObjectIndexForMethod(int) const;
-
- QByteArray toData() const {
- if (m_stringCountLoaded == m_stringCount - 1) {
- // zero-string is lazily loaded last
- const_cast<StringRef &>(m_zeroString).loadByteArrayData();
- }
- Q_ASSERT(m_stringCountLoaded == m_stringCount);
- return m_data;
- }
- static void fromData(QMetaObject *, const QMetaObject *parent, const QByteArray &);
-private:
- friend struct StringRef;
-
- QByteArray m_data;
- StringRef m_zeroString;
-
- void allocateStringData();
- QByteArrayData *m_stringData;
- int m_stringCount;
- int m_stringDataLength;
- int m_stringCountAllocated;
- int m_stringCountLoaded;
-};
-
-QFastMetaBuilder::StringRef::StringRef()
-: _b(0), _i(0), _o(0), _l(0)
-{
-}
-
-QFastMetaBuilder::StringRef::StringRef(const StringRef &o)
-: _b(o._b), _i(o._i), _o(o._o), _l(o._l)
-{
-}
-
-QFastMetaBuilder::StringRef &QFastMetaBuilder::StringRef::operator=(const StringRef &o)
-{
- _b = o._b;
- _i = o._i;
- _o = o._o;
- _l = o._l;
- return *this;
-}
-
-bool QFastMetaBuilder::StringRef::isEmpty() const
-{
- return _l == 0;
-}
-
-QFastMetaBuilder *QFastMetaBuilder::StringRef::builder() const
-{
- return _b;
-}
-
-int QFastMetaBuilder::StringRef::index() const
-{
- return _i;
-}
-
-char *QFastMetaBuilder::StringRef::data()
-{
- Q_ASSERT(_b);
- if (_b->m_stringCountAllocated < _b->m_stringCount)
- _b->allocateStringData();
- return reinterpret_cast<char *>(&_b->m_stringData[_b->m_stringCount]) + _o;
-}
-
-int QFastMetaBuilder::StringRef::length() const
-{
- return _l;
-}
-
-void QFastMetaBuilder::StringRef::load(const QHashedStringRef &str)
-{
- Q_ASSERT(str.utf8length() == _l);
- str.writeUtf8(data());
- *(data() + _l) = 0;
- loadByteArrayData();
-}
-
-void QFastMetaBuilder::StringRef::load(const QByteArray &str)
-{
- Q_ASSERT(str.length() == _l);
- strcpy(data(), str.constData());
- loadByteArrayData();
-}
-
-void QFastMetaBuilder::StringRef::load(const char *str)
-{
- Q_ASSERT(strlen(str) == (uint)_l);
- strcpy(data(), str);
- loadByteArrayData();
-}
-
-void QFastMetaBuilder::StringRef::loadByteArrayData()
-{
- if (_b->m_stringCountAllocated < _b->m_stringCount)
- _b->allocateStringData();
- Q_ASSERT(_b->m_stringCountLoaded < _b->m_stringCount);
-
- int offsetofCstrings = _b->m_stringCount * sizeof(QByteArrayData);
- qptrdiff offset = offsetofCstrings + _o - _i * sizeof(QByteArrayData);
-
- const QByteArrayData bad = Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(_l, offset);
- memcpy(&_b->m_stringData[_i], &bad, sizeof(QByteArrayData));
-
- ++_b->m_stringCountLoaded;
-}
-
-QT_END_NAMESPACE
-
-#endif // QFASTMETABUILDER_P_H
-
diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h
index f8099d508b..cdc1577987 100644
--- a/src/qml/qml/ftw/qhashedstring_p.h
+++ b/src/qml/qml/ftw/qhashedstring_p.h
@@ -157,6 +157,8 @@ public:
QString toString() const;
+ inline bool isLatin1() const;
+
inline int utf8length() const;
QByteArray toUtf8() const;
void writeUtf8(char *) const;
@@ -1337,6 +1339,13 @@ int QHashedStringRef::utf8length() const
return m_utf8length;
}
+bool QHashedStringRef::isLatin1() const
+{
+ for (int ii = 0; ii < m_length; ++ii)
+ if (m_data[ii].unicode() > 127) return false;
+ return true;
+}
+
bool QHashedStringRef::startsWithUpper() const
{
if (m_length < 1) return false;
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index 9a3ce65ad3..1a16c07a75 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -242,9 +242,9 @@ void QQmlAbstractBoundSignal::removeFromObject()
}
}
-QQmlBoundSignal::QQmlBoundSignal(QObject *scope, const QMetaMethod &signal,
- QObject *owner, QQmlEngine *engine)
-: m_expression(0), m_params(0), m_scope(scope), m_index(signal.methodIndex())
+QQmlBoundSignal::QQmlBoundSignal(QObject *scope, int signal, QObject *owner,
+ QQmlEngine *engine)
+: m_expression(0), m_params(0), m_scope(scope), m_index(signal)
{
setParamsValid(false);
setIsEvaluating(false);
@@ -257,11 +257,15 @@ QQmlBoundSignal::QQmlBoundSignal(QObject *scope, const QMetaMethod &signal,
index refers to 'aSignal()', get the index of 'aSignal(int)'.
This ensures that 'parameter' will be available from QML.
*/
- if (signal.attributes() & QMetaMethod::Cloned) {
- do {
+ if (QQmlData::get(scope, false) && QQmlData::get(scope, false)->propertyCache) {
+ QQmlPropertyCache *cache = QQmlData::get(scope, false)->propertyCache;
+ while (cache->method(m_index)->isCloned())
+ --m_index;
+ } else {
+ while (scope->metaObject()->method(m_index).attributes() & QMetaMethod::Cloned)
--m_index;
- } while (scope->metaObject()->method(m_index).attributes() & QMetaMethod::Cloned);
}
+
QQmlNotifierEndpoint::connect(scope, m_index, engine);
}
@@ -328,9 +332,12 @@ void QQmlBoundSignal::subscriptionCallback(QQmlNotifierEndpoint *e, void **a)
s->setIsEvaluating(true);
if (!s->paramsValid()) {
- QMetaMethod signal = s->m_scope->metaObject()->method(s->m_index);
- if (!signal.parameterTypes().isEmpty())
+ QList<QByteArray> names = QQmlPropertyCache::methodParameterNames(*s->m_scope, s->m_index);
+ if (!names.isEmpty()) {
+ QMetaMethod signal = s->m_scope->metaObject()->method(s->m_index);
s->m_params = new QQmlBoundSignalParameters(signal, s);
+ }
+
s->setParamsValid(true);
}
diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h
index e3ef65ed7f..b7f3e5f885 100644
--- a/src/qml/qml/qqmlboundsignal_p.h
+++ b/src/qml/qml/qqmlboundsignal_p.h
@@ -137,7 +137,7 @@ class Q_QML_PRIVATE_EXPORT QQmlBoundSignal : public QQmlAbstractBoundSignal,
public QQmlNotifierEndpoint
{
public:
- QQmlBoundSignal(QObject *scope, const QMetaMethod &signal, QObject *owner, QQmlEngine *engine);
+ QQmlBoundSignal(QObject *scope, int signal, QObject *owner, QQmlEngine *engine);
virtual ~QQmlBoundSignal();
int index() const;
diff --git a/src/qml/qml/qqmlcompileddata.cpp b/src/qml/qml/qqmlcompileddata.cpp
index 6e6da6ae0d..49f00944d5 100644
--- a/src/qml/qml/qqmlcompileddata.cpp
+++ b/src/qml/qml/qqmlcompileddata.cpp
@@ -55,21 +55,6 @@
QT_BEGIN_NAMESPACE
-int QQmlCompiledData::pack(const char *data, size_t size)
-{
- const char *p = packData.constData();
- unsigned int ps = packData.size();
-
- for (unsigned int ii = 0; (ii + size) <= ps; ii += sizeof(int)) {
- if (0 == ::memcmp(p + ii, data, size))
- return ii;
- }
-
- int rv = packData.size();
- packData.append(data, int(size));
- return rv;
-}
-
int QQmlCompiledData::indexForString(const QString &data)
{
int idx = primitives.indexOf(data);
@@ -101,7 +86,8 @@ int QQmlCompiledData::indexForUrl(const QUrl &data)
}
QQmlCompiledData::QQmlCompiledData(QQmlEngine *engine)
-: engine(engine), importCache(0), root(0), rootPropertyCache(0)
+: engine(engine), importCache(0), metaTypeId(-1), listMetaTypeId(-1), isRegisteredWithEngine(false),
+ rootPropertyCache(0)
{
Q_ASSERT(engine);
@@ -118,6 +104,9 @@ void QQmlCompiledData::destroy()
QQmlCompiledData::~QQmlCompiledData()
{
+ if (isRegisteredWithEngine)
+ QQmlEnginePrivate::get(engine)->unregisterCompositeType(this);
+
clear();
for (int ii = 0; ii < types.count(); ++ii) {
@@ -149,16 +138,6 @@ void QQmlCompiledData::clear()
qPersistentDispose(programs[ii].bindings);
}
-const QMetaObject *QQmlCompiledData::TypeReference::metaObject() const
-{
- if (type) {
- return type->metaObject();
- } else {
- Q_ASSERT(component);
- return component->root;
- }
-}
-
/*!
Returns the property cache, if one alread exists. The cache is not referenced.
*/
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index b00f4b3294..2e26d94047 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -44,7 +44,6 @@
#include "qqmlpropertyvaluesource.h"
#include "qqmlcomponent.h"
#include <private/qmetaobjectbuilder_p.h>
-#include <private/qfastmetabuilder_p.h>
#include "qqmlstringconverters_p.h"
#include "qqmlengine_p.h"
#include "qqmlengine.h"
@@ -217,8 +216,7 @@ bool QQmlCompiler::isSignalPropertyName(const QHashedStringRef &name)
This test corresponds to action taken by genLiteralAssignment(). Any change
made here, must have a corresponding action in genLiteralAssigment().
*/
-bool QQmlCompiler::testLiteralAssignment(QQmlScript::Property *prop,
- QQmlScript::Value *v)
+bool QQmlCompiler::testLiteralAssignment(QQmlScript::Property *prop, QQmlScript::Value *v)
{
const QQmlScript::Variant &value = v->value;
@@ -226,7 +224,7 @@ bool QQmlCompiler::testLiteralAssignment(QQmlScript::Property *prop,
COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
if (prop->core.isEnum()) {
- QMetaProperty p = prop->parent->metaObject()->property(prop->index);
+ QMetaProperty p = prop->parent->metatype->firstCppMetaObject()->property(prop->index);
int enumValue;
bool ok;
if (p.isFlagType()) {
@@ -438,7 +436,7 @@ void QQmlCompiler::genLiteralAssignment(QQmlScript::Property *prop,
if (v->value.isNumber()) {
double n = v->value.asNumber();
if (double(int(n)) == n) {
- if (prop->core.isVMEProperty()) {
+ if (prop->core.isVarProperty()) {
Instruction::StoreVarInteger instr;
instr.propertyIndex = prop->index;
instr.value = int(n);
@@ -450,7 +448,7 @@ void QQmlCompiler::genLiteralAssignment(QQmlScript::Property *prop,
output->addInstruction(instr);
}
} else {
- if (prop->core.isVMEProperty()) {
+ if (prop->core.isVarProperty()) {
Instruction::StoreVarDouble instr;
instr.propertyIndex = prop->index;
instr.value = n;
@@ -463,7 +461,7 @@ void QQmlCompiler::genLiteralAssignment(QQmlScript::Property *prop,
}
}
} else if (v->value.isBoolean()) {
- if (prop->core.isVMEProperty()) {
+ if (prop->core.isVarProperty()) {
Instruction::StoreVarBool instr;
instr.propertyIndex = prop->index;
instr.value = v->value.asBoolean();
@@ -475,7 +473,7 @@ void QQmlCompiler::genLiteralAssignment(QQmlScript::Property *prop,
output->addInstruction(instr);
}
} else {
- if (prop->core.isVMEProperty()) {
+ if (prop->core.isVarProperty()) {
Instruction::StoreVar instr;
instr.propertyIndex = prop->index;
instr.value = output->indexForString(v->value.asString());
@@ -944,15 +942,18 @@ void QQmlCompiler::compileTree(QQmlScript::Object *tree)
output->addInstruction(done);
Q_ASSERT(tree->metatype);
-
- if (tree->metadata.isEmpty()) {
- output->root = tree->metatype;
+ if (!tree->synthdata.isEmpty()) {
+ enginePrivate->registerCompositeType(output);
+ } else if (output->types.at(tree->type).component) {
+ output->metaTypeId = output->types.at(tree->type).component->metaTypeId;
+ output->listMetaTypeId = output->types.at(tree->type).component->listMetaTypeId;
} else {
- static_cast<QMetaObject &>(output->rootData) = *tree->metaObject();
- output->root = &output->rootData;
+ Q_ASSERT(output->types.at(tree->type).type);
+ output->metaTypeId = output->types.at(tree->type).type->typeId();
+ output->listMetaTypeId = output->types.at(tree->type).type->qListTypeId();
}
- if (!tree->metadata.isEmpty())
- enginePrivate->registerCompositeType(output->root);
+ if (!tree->synthdata.isEmpty())
+ enginePrivate->registerCompositeType(output);
}
static bool QStringList_contains(const QStringList &list, const QHashedStringRef &string)
@@ -970,11 +971,11 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
componentStats->componentStat.objects++;
Q_ASSERT (obj->type != -1);
- const QQmlCompiledData::TypeReference &tr = output->types.at(obj->type);
- obj->metatype = tr.metaObject();
+ QQmlCompiledData::TypeReference &tr = output->types[obj->type];
+ obj->metatype = tr.createPropertyCache(engine);
- // This object is a "Component" element
- if (tr.type && obj->metatype == &QQmlComponent::staticMetaObject) {
+ // This object is a "Component" element.
+ if (tr.type && obj->metatype->metaObject() == &QQmlComponent::staticMetaObject) {
COMPILE_CHECK(buildComponent(obj, ctxt));
return true;
}
@@ -999,7 +1000,7 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
// Create the synthesized meta object, ignoring aliases
COMPILE_CHECK(checkDynamicMeta(obj));
COMPILE_CHECK(mergeDynamicMetaProperties(obj));
- COMPILE_CHECK(buildDynamicMeta(obj, IgnoreAliases));
+ COMPILE_CHECK(buildDynamicMeta(obj, Normal));
// Find the native type and check for the QQmlParserStatus interface
QQmlType *type = toQmlType(obj);
@@ -1036,54 +1037,22 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
Property *explicitProperty = 0;
- const QMetaObject *mo = obj->metatype;
- int idx = mo->indexOfClassInfo("DefaultProperty");
- if (idx != -1) {
- QMetaClassInfo info = mo->classInfo(idx);
- const char *p = info.value();
- if (p) {
- int plen = 0;
- char ord = 0;
- while (char c = p[plen++]) { ord |= c; };
- --plen;
-
- if (ord & 0x80) {
- // Utf8 - unoptimal, but seldom hit
- QString *s = pool->NewString(QString::fromUtf8(p, plen));
- QHashedStringRef r(*s);
-
- if (obj->propertiesHashField.test(r.hash())) {
- for (Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) {
- if (ep->name() == r) {
- explicitProperty = ep;
- break;
- }
- }
- }
+ QString defaultPropertyName = obj->metatype->defaultPropertyName();
+ if (!defaultPropertyName.isEmpty()) {
+ QString *s = pool->NewString(defaultPropertyName);
+ QHashedStringRef r(*s);
- if (!explicitProperty)
- defaultProperty->setName(r);
-
- } else {
- QHashedCStringRef r(p, plen);
-
- if (obj->propertiesHashField.test(r.hash())) {
- for (Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) {
- if (ep->name() == r) {
- explicitProperty = ep;
- break;
- }
- }
- }
-
- if (!explicitProperty) {
- // Set the default property name
- QChar *buffer = pool->NewRawArray<QChar>(r.length());
- r.writeUtf16(buffer);
- defaultProperty->setName(QHashedStringRef(buffer, r.length(), r.hash()));
+ if (obj->propertiesHashField.test(r.hash())) {
+ for (Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) {
+ if (ep->name() == r) {
+ explicitProperty = ep;
+ break;
}
}
}
+
+ if (!explicitProperty)
+ defaultProperty->setName(r);
}
if (explicitProperty && !explicitProperty->value && !explicitProperty->values.isEmpty()) {
@@ -1189,7 +1158,7 @@ bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ct
void QQmlCompiler::genObject(QQmlScript::Object *obj)
{
QQmlCompiledData::TypeReference &tr = output->types[obj->type];
- if (tr.type && obj->metatype == &QQmlComponent::staticMetaObject) {
+ if (tr.type && obj->metatype->metaObject() == &QQmlComponent::staticMetaObject) {
genComponent(obj);
return;
}
@@ -1240,9 +1209,8 @@ void QQmlCompiler::genObject(QQmlScript::Object *obj)
}
// Setup the synthesized meta object if necessary
- if (!obj->metadata.isEmpty()) {
+ if (!obj->synthdata.isEmpty()) {
Instruction::StoreMetaObject meta;
- meta.data = output->indexForByteArray(obj->metadata);
meta.aliasData = output->indexForByteArray(obj->synthdata);
meta.propertyCache = output->propertyCaches.count();
@@ -1250,17 +1218,6 @@ void QQmlCompiler::genObject(QQmlScript::Object *obj)
Q_ASSERT(propertyCache);
propertyCache->addref();
- // Add flag for alias properties
- if (!obj->synthdata.isEmpty()) {
- const QQmlVMEMetaData *vmeMetaData =
- reinterpret_cast<const QQmlVMEMetaData *>(obj->synthdata.constData());
- for (int ii = 0; ii < vmeMetaData->aliasCount; ++ii) {
- int index = obj->metaObject()->propertyOffset() + vmeMetaData->propertyCount + ii;
- QQmlPropertyData *data = propertyCache->property(index);
- data->setFlags(data->getFlags() | QQmlPropertyData::IsAlias);
- }
- }
-
if (obj == unitRoot) {
propertyCache->addref();
output->rootPropertyCache = propertyCache;
@@ -1388,11 +1345,14 @@ void QQmlCompiler::genObjectBody(QQmlScript::Object *obj)
fetch.line = prop->location.start.line;
output->addInstruction(fetch);
- if (!prop->value->metadata.isEmpty()) {
+ if (!prop->value->synthdata.isEmpty()) {
Instruction::StoreMetaObject meta;
- meta.data = output->indexForByteArray(prop->value->metadata);
meta.aliasData = output->indexForByteArray(prop->value->synthdata);
- meta.propertyCache = -1;
+ meta.propertyCache = output->propertyCaches.count();
+ QQmlPropertyCache *propertyCache = prop->value->synthCache;
+ Q_ASSERT(propertyCache);
+ propertyCache->addref();
+ output->propertyCaches << propertyCache;
output->addInstruction(meta);
}
@@ -1665,7 +1625,7 @@ int QQmlCompiler::translationContextIndex()
bool QQmlCompiler::buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj,
const BindingContext &ctxt)
{
- Q_ASSERT(obj->metaObject());
+ Q_ASSERT(obj->metatype);
const QHashedStringRef &propName = prop->name();
@@ -1754,9 +1714,6 @@ bool QQmlCompiler::buildProperty(QQmlScript::Property *prop,
if (prop->isEmpty())
COMPILE_EXCEPTION(prop, tr("Empty property assignment"));
- const QMetaObject *metaObject = obj->metaObject();
- Q_ASSERT(metaObject);
-
if (isAttachedPropertyName(prop->name())) {
// Setup attached property data
@@ -1784,7 +1741,7 @@ bool QQmlCompiler::buildProperty(QQmlScript::Property *prop,
Q_ASSERT(type->attachedPropertiesFunction());
prop->index = type->attachedPropertiesId();
- prop->value->metatype = type->attachedPropertiesType();
+ prop->value->metatype = enginePrivate->cache(type->attachedPropertiesType());
} else {
// Setup regular property data
bool notInRevision = false;
@@ -1803,13 +1760,13 @@ bool QQmlCompiler::buildProperty(QQmlScript::Property *prop,
prop->index = d->coreIndex;
prop->core = *d;
} else if (prop->isDefault) {
- QMetaProperty p = QQmlMetaType::defaultProperty(metaObject);
- QQmlPropertyData defaultPropertyData;
- defaultPropertyData.load(p, engine);
- if (p.name())
- prop->setName(QLatin1String(p.name()));
- prop->core = defaultPropertyData;
- prop->index = prop->core.coreIndex;
+ QString defaultPropertyName = obj->metatype->defaultPropertyName();
+
+ if (!defaultPropertyName.isEmpty()) {
+ prop->setName(defaultPropertyName);
+ prop->core = *obj->metatype->defaultProperty();
+ prop->index = prop->core.coreIndex;
+ }
}
// We can't error here as the "id" property does not require a
@@ -1901,7 +1858,7 @@ bool QQmlCompiler::buildPropertyInNamespace(QQmlImportNamespace *ns,
Q_ASSERT(type->attachedPropertiesFunction());
prop->index = type->index();
- prop->value->metatype = type->attachedPropertiesType();
+ prop->value->metatype = enginePrivate->cache(type->attachedPropertiesType());
COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt));
}
@@ -1979,7 +1936,7 @@ void QQmlCompiler::genPropertyAssignment(QQmlScript::Property *prop,
} else if (prop->type == QMetaType::QVariant) {
- if (prop->core.isVMEProperty()) {
+ if (prop->core.isVarProperty()) {
Instruction::StoreVarObject store;
store.line = v->object->location.start.line;
store.propertyIndex = prop->index;
@@ -2178,7 +2135,7 @@ bool QQmlCompiler::buildGroupedProperty(QQmlScript::Property *prop,
} else {
// Load the nested property's meta type
- prop->value->metatype = enginePrivate->metaObjectForType(prop->type);
+ prop->value->metatype = enginePrivate->propertyCacheForType(prop->type);
if (!prop->value->metatype)
COMPILE_EXCEPTION(prop, tr("Invalid grouped property access"));
@@ -2206,7 +2163,7 @@ bool QQmlCompiler::buildValueTypeProperty(QObject *type,
if (obj->defaultProperty)
COMPILE_EXCEPTION(obj, tr("Invalid property use"));
- obj->metatype = type->metaObject();
+ obj->metatype = enginePrivate->cache(type);
for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
@@ -2396,22 +2353,22 @@ bool QQmlCompiler::buildPropertyObjectAssignment(QQmlScript::Property *prop,
// meta object earlier to test for assignability. It doesn't matter
// that there may still be outstanding synthesized meta object changes
// on this type, as they are not relevant for assignability testing
- v->object->metatype = output->types.at(v->object->type).metaObject();
- Q_ASSERT(v->object->metaObject());
+ v->object->metatype = output->types[v->object->type].createPropertyCache(engine);
+ Q_ASSERT(v->object->metatype);
// We want to raw metaObject here as the raw metaobject is the
// actual property type before we applied any extensions that might
// effect the properties on the type, but don't effect assignability
- const QMetaObject *propertyMetaObject = enginePrivate->rawMetaObjectForType(prop->type);
+ QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(prop->type);
// Will be true if the assgned type inherits propertyMetaObject
bool isAssignable = false;
// Determine isAssignable value
if (propertyMetaObject) {
- const QMetaObject *c = v->object->metatype;
- while(c) {
- isAssignable |= (QQmlPropertyPrivate::equal(c, propertyMetaObject));
- c = c->superClass();
+ QQmlPropertyCache *c = v->object->metatype;
+ while (c && !isAssignable) {
+ isAssignable |= c == propertyMetaObject;
+ c = c->parent();
}
}
@@ -2420,12 +2377,12 @@ bool QQmlCompiler::buildPropertyObjectAssignment(QQmlScript::Property *prop,
COMPILE_CHECK(buildObject(v->object, ctxt));
v->type = Value::CreatedObject;
- } else if (propertyMetaObject == &QQmlComponent::staticMetaObject) {
+ } else if (propertyMetaObject && propertyMetaObject->metaObject() == &QQmlComponent::staticMetaObject) {
// Automatic "Component" insertion
QQmlScript::Object *root = v->object;
QQmlScript::Object *component = pool->New<Object>();
component->type = componentTypeRef();
- component->metatype = &QQmlComponent::staticMetaObject;
+ component->metatype = enginePrivate->cache(&QQmlComponent::staticMetaObject);
component->location = root->location;
QQmlScript::Value *componentValue = pool->New<Value>();
componentValue->object = root;
@@ -2465,8 +2422,8 @@ bool QQmlCompiler::buildPropertyOnAssignment(QQmlScript::Property *prop,
// meta object earlier to test for assignability. It doesn't matter
// that there may still be outstanding synthesized meta object changes
// on this type, as they are not relevant for assignability testing
- v->object->metatype = output->types.at(v->object->type).metaObject();
- Q_ASSERT(v->object->metaObject());
+ v->object->metatype = output->types[v->object->type].createPropertyCache(engine);
+ Q_ASSERT(v->object->metatype);
// Will be true if the assigned type inherits QQmlPropertyValueSource
bool isPropertyValue = false;
@@ -2481,7 +2438,7 @@ bool QQmlCompiler::buildPropertyOnAssignment(QQmlScript::Property *prop,
// Assign as a property value source
COMPILE_CHECK(buildObject(v->object, ctxt));
- if (isPropertyInterceptor && prop->parent->synthdata.isEmpty())
+ if (isPropertyInterceptor && baseObj->synthdata.isEmpty())
buildDynamicMeta(baseObj, ForceCreation);
v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor;
} else {
@@ -2537,7 +2494,7 @@ bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop,
if (!prop->core.isEnum() && !isIntProp)
return true;
- QMetaProperty mprop = obj->metaObject()->property(prop->index);
+ QMetaProperty mprop = obj->metatype->firstCppMetaObject()->property(prop->index);
if (!prop->core.isWritable() && !prop->isReadOnlyDeclaration)
COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
@@ -2775,7 +2732,27 @@ bool QQmlCompiler::mergeDynamicMetaProperties(QQmlScript::Object *obj)
return true;
}
-Q_GLOBAL_STATIC(QAtomicInt, classIndexCounter)
+#include <private/qqmljsparser_p.h>
+
+static QStringList astNodeToStringList(QQmlJS::AST::Node *node)
+{
+ if (node->kind == QQmlJS::AST::Node::Kind_IdentifierExpression) {
+ QString name =
+ static_cast<QQmlJS::AST::IdentifierExpression *>(node)->name.toString();
+ return QStringList() << name;
+ } else if (node->kind == QQmlJS::AST::Node::Kind_FieldMemberExpression) {
+ QQmlJS::AST::FieldMemberExpression *expr = static_cast<QQmlJS::AST::FieldMemberExpression *>(node);
+
+ QStringList rv = astNodeToStringList(expr->base);
+ if (rv.isEmpty())
+ return rv;
+ rv.append(expr->name.toString());
+ return rv;
+ }
+ return QStringList();
+}
+
+static QAtomicInt classIndexCounter(0);
bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mode)
{
@@ -2788,74 +2765,7 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
obj->dynamicSlots.isEmpty())
return true;
- bool resolveAlias = (mode == ResolveAliases);
-
- const Object::DynamicProperty *defaultProperty = 0;
- int aliasCount = 0;
- int varPropCount = 0;
- int totalPropCount = 0;
- int firstPropertyVarIndex = 0;
-
- for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
-
- if (p->type == Object::DynamicProperty::Alias)
- aliasCount++;
- if (p->type == Object::DynamicProperty::Var)
- varPropCount++;
-
- if (p->isDefaultProperty &&
- (resolveAlias || p->type != Object::DynamicProperty::Alias))
- defaultProperty = p;
-
- if (!resolveAlias) {
- // No point doing this for both the alias and non alias cases
- QQmlPropertyData *d = property(obj, p->name);
- if (d && d->isFinal())
- COMPILE_EXCEPTION(p, tr("Cannot override FINAL property"));
- }
- }
-
- bool buildData = resolveAlias || aliasCount == 0;
-
- QByteArray dynamicData;
- if (buildData) {
- typedef QQmlVMEMetaData VMD;
-
- dynamicData = QByteArray(sizeof(QQmlVMEMetaData) +
- (obj->dynamicProperties.count() - aliasCount) * sizeof(VMD::PropertyData) +
- obj->dynamicSlots.count() * sizeof(VMD::MethodData) +
- aliasCount * sizeof(VMD::AliasData), 0);
- }
-
- int uniqueClassId = classIndexCounter()->fetchAndAddRelaxed(1);
-
- QByteArray newClassName = obj->metatype->className();
- newClassName.append("_QML_");
- newClassName.append(QByteArray::number(uniqueClassId));
-
- if (compileState->root == obj && !compileState->nested) {
- QString path = output->url.path();
- int lastSlash = path.lastIndexOf(QLatin1Char('/'));
- if (lastSlash > -1) {
- QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5);
- if (!nameBase.isEmpty() && nameBase.at(0).isUpper())
- newClassName = nameBase.toUtf8() + "_QMLTYPE_" + QByteArray::number(uniqueClassId);
- }
- }
-
- // Size of the array that describes parameter types & names
- int paramDataSize = (obj->aggregateDynamicSignalParameterCount() + obj->aggregateDynamicSlotParameterCount()) * 2
- + obj->dynamicProperties.count() // for Changed() signals return types
- // Return "parameters" don't have names
- - (obj->dynamicSignals.count() + obj->dynamicSlots.count());
-
- QFastMetaBuilder builder;
- int paramIndex;
- QFastMetaBuilder::StringRef classNameRef = builder.init(newClassName.length(),
- obj->dynamicProperties.count() - (resolveAlias?0:aliasCount),
- obj->dynamicSlots.count(),
- obj->dynamicSignals.count() + obj->dynamicProperties.count(),
- defaultProperty?1:0, paramDataSize, &paramIndex);
+ Q_ASSERT(obj->synthCache == 0);
struct TypeData {
Object::DynamicProperty::Type dtype;
@@ -2876,456 +2786,521 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
};
static const int builtinTypeCount = sizeof(builtinTypes) / sizeof(TypeData);
- // Reserve dynamic properties
- if (obj->dynamicProperties.count()) {
- typedef QQmlVMEMetaData VMD;
+ QByteArray newClassName;
- int effectivePropertyIndex = 0;
- for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
+ if (compileState->root == obj && !compileState->nested) {
+ QString path = output->url.path();
+ int lastSlash = path.lastIndexOf(QLatin1Char('/'));
+ if (lastSlash > -1) {
+ QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5);
+ if (!nameBase.isEmpty() && nameBase.at(0).isUpper())
+ newClassName = nameBase.toUtf8() + "_QMLTYPE_" +
+ QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1));
+ }
+ }
+ if (newClassName.isEmpty()) {
+ newClassName = QQmlMetaObject(obj->metatype).className();
+ newClassName.append("_QML_");
+ newClassName.append(QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1)));
+ }
+ QQmlPropertyCache *cache = obj->metatype->copyAndReserve(engine, obj->dynamicProperties.count(),
+ obj->dynamicProperties.count() +
+ obj->dynamicSignals.count() +
+ obj->dynamicSlots.count(),
+ obj->dynamicProperties.count() +
+ obj->dynamicSignals.count());
- // Reserve space for name
- if (p->type != Object::DynamicProperty::Alias || resolveAlias)
- p->nameRef = builder.newString(p->name.utf8length());
+ cache->_dynamicClassName = newClassName;
- int metaType = 0;
- int propertyType = 0; // for VMD
- bool readonly = false;
+ int cStringNameCount = 0;
- if (p->type == Object::DynamicProperty::Alias) {
- continue;
- } else if (p->type < builtinTypeCount) {
- Q_ASSERT(builtinTypes[p->type].dtype == p->type);
- metaType = builtinTypes[p->type].metaType;
- propertyType = metaType;
+ int aliasCount = 0;
+ int varPropCount = 0;
- } else {
- Q_ASSERT(p->type == Object::DynamicProperty::CustomList ||
- p->type == Object::DynamicProperty::Custom);
-
- // XXX don't double resolve this in the case of an alias run
-
- QByteArray customTypeName;
- QQmlType *qmltype = 0;
- QString url;
- if (!unit->imports().resolveType(p->customType, &qmltype, &url, 0, 0, 0))
- COMPILE_EXCEPTION(p, tr("Invalid property type"));
-
- if (!qmltype) {
- QQmlTypeData *tdata = enginePrivate->typeLoader.getType(QUrl(url));
- Q_ASSERT(tdata);
- Q_ASSERT(tdata->isComplete());
- customTypeName = tdata->compiledData()->root->className();
- tdata->release();
- } else {
- customTypeName = qmltype->typeName();
- }
+ for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
+ p = obj->dynamicProperties.next(p)) {
- if (p->type == Object::DynamicProperty::Custom) {
- customTypeName += '*';
- propertyType = QMetaType::QObjectStar;
- } else {
- readonly = true;
- customTypeName = QByteArrayLiteral("QQmlListProperty<") + customTypeName + '>';
- propertyType = qMetaTypeId<QQmlListProperty<QObject> >();
- }
+ if (p->type == Object::DynamicProperty::Alias)
+ aliasCount++;
+ else if (p->type == Object::DynamicProperty::Var)
+ varPropCount++;
- metaType = QMetaType::type(customTypeName);
- Q_ASSERT(metaType != QMetaType::UnknownType);
- Q_ASSERT(metaType != QMetaType::Void);
- }
+ if (p->name.isLatin1()) {
+ p->nameIndex = cStringNameCount;
+ cStringNameCount += p->name.length() + 7 /* strlen("Changed") */;
+ }
- if (p->type == Object::DynamicProperty::Var)
- continue;
+ // No point doing this for both the alias and non alias cases
+ QQmlPropertyData *d = property(obj, p->name);
+ if (d && d->isFinal())
+ COMPILE_EXCEPTION(p, tr("Cannot override FINAL property"));
+ }
- if (p->isReadOnly)
- readonly = true;
+ for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
+ if (s->name.isLatin1()) {
+ s->nameIndex = cStringNameCount;
+ cStringNameCount += s->name.length();
+ }
+ }
- if (buildData) {
- VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- vmd->propertyCount++;
- (vmd->propertyData() + effectivePropertyIndex)->propertyType = propertyType;
- }
+ for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
+ if (s->name.isLatin1()) {
+ s->nameIndex = cStringNameCount;
+ cStringNameCount += s->name.length();
+ }
+ }
- builder.setProperty(effectivePropertyIndex, p->nameRef, metaType,
- readonly?QFastMetaBuilder::None:QFastMetaBuilder::Writable,
- effectivePropertyIndex);
+ char *cStringData = 0;
+ if (cStringNameCount) {
+ cache->_dynamicStringData.resize(cStringNameCount);
+ cStringData = cache->_dynamicStringData.data();
- p->changedNameRef = builder.newString(p->name.utf8length() + Changed_string.size());
- builder.setSignal(effectivePropertyIndex, p->changedNameRef, paramIndex);
- paramIndex++;
+ for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
+ p = obj->dynamicProperties.next(p)) {
- effectivePropertyIndex++;
- }
+ if (p->nameIndex == -1) continue;
- if (varPropCount) {
- VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- if (buildData)
- vmd->varPropertyCount = varPropCount;
- firstPropertyVarIndex = effectivePropertyIndex;
- totalPropCount = varPropCount + effectivePropertyIndex;
- for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
- if (p->type == Object::DynamicProperty::Var) {
- if (buildData) {
- vmd->propertyCount++;
- (vmd->propertyData() + effectivePropertyIndex)->propertyType = QMetaType::QVariant;
- }
+ char *myData = cStringData + p->nameIndex;
+ for (int ii = 0; ii < p->name.length(); ++ii)
+ *myData++ = p->name.at(ii).unicode();
+ *myData++ = 'C'; *myData++ = 'h'; *myData++ = 'a'; *myData++ = 'n';
+ *myData++ = 'g'; *myData++ = 'e'; *myData++ = 'd';
+ }
- builder.setProperty(effectivePropertyIndex, p->nameRef,
- QMetaType::QVariant,
- p->isReadOnly?QFastMetaBuilder::None:QFastMetaBuilder::Writable,
- effectivePropertyIndex);
+ for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
- p->changedNameRef = builder.newString(p->name.utf8length() + Changed_string.size());
- builder.setSignal(effectivePropertyIndex, p->changedNameRef, paramIndex);
- paramIndex++;
+ if (s->nameIndex == -1) continue;
- effectivePropertyIndex++;
- }
- }
+ char *myData = cStringData + s->nameIndex;
+ for (int ii = 0; ii < s->name.length(); ++ii)
+ *myData++ = s->name.at(ii).unicode();
}
-
- if (aliasCount) {
- int aliasIndex = 0;
- for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
- if (p->type == Object::DynamicProperty::Alias) {
- if (resolveAlias) {
- Q_ASSERT(buildData);
- ((QQmlVMEMetaData *)dynamicData.data())->aliasCount++;
- COMPILE_CHECK(compileAlias(builder, dynamicData, obj, effectivePropertyIndex,
- aliasIndex, *p));
- }
- // Even if we aren't resolving the alias, we need a fake signal so that the
- // metaobject remains consistent across the resolve and non-resolve alias runs
- p->changedNameRef = builder.newString(p->name.utf8length() + Changed_string.size());
- builder.setSignal(effectivePropertyIndex, p->changedNameRef, paramIndex);
- paramIndex++;
- effectivePropertyIndex++;
- aliasIndex++;
- }
- }
+
+ for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s;
+ s = obj->dynamicSignals.next(s)) {
+
+ if (s->nameIndex == -1) continue;
+
+ char *myData = cStringData + s->nameIndex;
+ for (int ii = 0; ii < s->name.length(); ++ii)
+ *myData++ = s->name.at(ii).unicode();
}
}
- // Reserve default property
- QFastMetaBuilder::StringRef defPropRef;
- if (defaultProperty) {
- defPropRef = builder.newString(int(sizeof("DefaultProperty")) - 1);
- builder.setClassInfo(0, defPropRef, defaultProperty->nameRef);
+ QByteArray dynamicData;
+ typedef QQmlVMEMetaData VMD;
+
+ dynamicData = QByteArray(sizeof(QQmlVMEMetaData) +
+ obj->dynamicProperties.count() * sizeof(VMD::PropertyData) +
+ obj->dynamicSlots.count() * sizeof(VMD::MethodData) +
+ aliasCount * sizeof(VMD::AliasData), 0);
+
+ int effectivePropertyIndex = cache->propertyIndexCacheStart;
+ int effectiveMethodIndex = cache->methodIndexCacheStart;
+
+ // First set up notify signals for properties - first normal, then var, then alias
+ enum { NSS_Normal = 0, NSS_Var = 1, NSS_Alias = 2 };
+ for (int ii = NSS_Normal; ii <= NSS_Alias; ++ii) { // 0 == normal, 1 == var, 2 == alias
+
+ if (ii == NSS_Var && varPropCount == 0) continue;
+ else if (ii == NSS_Alias && aliasCount == 0) continue;
+
+ for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
+ p = obj->dynamicProperties.next(p)) {
+
+ if ((ii == NSS_Normal && (p->type == Object::DynamicProperty::Alias ||
+ p->type == Object::DynamicProperty::Var)) ||
+ ((ii == NSS_Var) && (p->type != Object::DynamicProperty::Var)) ||
+ ((ii == NSS_Alias) && (p->type != Object::DynamicProperty::Alias)))
+ continue;
+
+ quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
+ QQmlPropertyData::IsVMESignal;
+
+ if (p->nameIndex != -1) {
+ QHashedCStringRef changedSignalName(cStringData + p->nameIndex,
+ p->name.length() + 7 /* strlen("Changed") */);
+ cache->appendSignal(changedSignalName, flags, effectiveMethodIndex++);
+ } else {
+ QString changedSignalName = p->name.toString() + QLatin1String("Changed");
+
+ cache->appendSignal(changedSignalName, flags, effectiveMethodIndex++);
+ }
+ }
}
- // Reserve dynamic signals
- int signalIndex = 0;
+ // Dynamic signals
for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
+ int paramCount = s->parameterNames.count();
- s->nameRef = builder.newString(s->name.utf8length());
+ QList<QByteArray> names;
+ QVarLengthArray<int, 10> paramTypes(paramCount?(paramCount + 1):0);
- int paramCount = s->parameterNames.count();
- QVarLengthArray<int, 10> paramTypes(paramCount);
if (paramCount) {
- s->parameterNamesRef = pool->NewRawList<QFastMetaBuilder::StringRef>(paramCount);
+ paramTypes[0] = paramCount;
+
for (int i = 0; i < paramCount; ++i) {
- s->parameterNamesRef[i] = builder.newString(s->parameterNames.at(i).utf8length());
Q_ASSERT(s->parameterTypes.at(i) < builtinTypeCount);
- paramTypes[i] = builtinTypes[s->parameterTypes.at(i)].metaType;
+ paramTypes[i + 1] = builtinTypes[s->parameterTypes.at(i)].metaType;
+ names.append(s->parameterNames.at(i).toString().toUtf8());
}
}
- if (buildData)
- ((QQmlVMEMetaData *)dynamicData.data())->signalCount++;
-
- builder.setSignal(signalIndex + obj->dynamicProperties.count(), s->nameRef,
- paramIndex, paramCount, paramTypes.constData(), s->parameterNamesRef.data());
- paramIndex += paramCount*2 + 1;
- ++signalIndex;
+ ((QQmlVMEMetaData *)dynamicData.data())->signalCount++;
+
+ quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
+ QQmlPropertyData::IsVMESignal;
+ if (paramCount)
+ flags |= QQmlPropertyData::HasArguments;
+
+ if (s->nameIndex != -1) {
+ QHashedCStringRef name(cStringData + s->nameIndex, s->name.length(), s->name.hash());
+ cache->appendSignal(name, flags, effectiveMethodIndex++,
+ paramCount?paramTypes.constData():0, names);
+ } else {
+ QString name = s->name.toString();
+ cache->appendSignal(name, flags, effectiveMethodIndex++,
+ paramCount?paramTypes.constData():0, names);
+ }
}
- // Reserve dynamic slots
- if (obj->dynamicSlots.count()) {
- typedef QQmlVMEMetaData VMD;
+ // Dynamic slots
+ for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
+ int paramCount = s->parameterNames.count();
- int methodIndex = 0;
- for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
- s->nameRef = builder.newString(s->name.utf8length());
- int paramCount = s->parameterNames.count();
-
- QVarLengthArray<int, 10> paramTypes(paramCount);
- if (paramCount) {
- s->parameterNamesRef = pool->NewRawList<QFastMetaBuilder::StringRef>(paramCount);
- for (int i = 0; i < paramCount; ++i) {
- s->parameterNamesRef[i] = builder.newString(s->parameterNames.at(i).size());
- paramTypes[i] = QMetaType::QVariant;
- }
- }
+ quint32 flags = QQmlPropertyData::IsFunction | QQmlPropertyData::IsVMEFunction;
- builder.setMethod(methodIndex, s->nameRef, paramIndex, paramCount,
- paramTypes.constData(), s->parameterNamesRef.data(), QMetaType::QVariant);
- paramIndex += paramCount*2 + 1;
-
- if (buildData) {
- QString funcScript;
- int namesSize = 0;
- if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1 /* commas */);
- funcScript.reserve(int(sizeof("(function ")) - 1 + s->name.length() + 1 /* lparen */ +
- namesSize + 1 /* rparen */ + s->body.length() + 1 /* rparen */);
- funcScript = QLatin1String("(function ") + s->name.toString() + QLatin1Char('(');
- for (int jj = 0; jj < paramCount; ++jj) {
- if (jj) funcScript.append(QLatin1Char(','));
- funcScript.append(QLatin1String(s->parameterNames.at(jj)));
- }
- funcScript += QLatin1Char(')') + s->body + QLatin1Char(')');
+ if (paramCount)
+ flags |= QQmlPropertyData::HasArguments;
- QByteArray utf8 = funcScript.toUtf8();
- VMD::MethodData methodData = { s->parameterNames.count(), 0,
- utf8.length(),
- s->location.start.line };
+ if (s->nameIndex != -1) {
+ QHashedCStringRef name(cStringData + s->nameIndex, s->name.length(), s->name.hash());
+ cache->appendMethod(name, flags, effectiveMethodIndex++, s->parameterNames);
+ } else {
+ QString name = s->name.toString();
+ cache->appendMethod(name, flags, effectiveMethodIndex++, s->parameterNames);
+ }
+ }
- VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- vmd->methodCount++;
- VMD::MethodData &md = *(vmd->methodData() + methodIndex);
- md = methodData;
- md.bodyOffset = dynamicData.size();
+ // Dynamic properties (except var and aliases)
+ effectiveMethodIndex = cache->methodIndexCacheStart;
+ for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
+ p = obj->dynamicProperties.next(p)) {
- dynamicData.append((const char *)utf8.constData(), utf8.length());
- }
+ if (p->type == Object::DynamicProperty::Alias ||
+ p->type == Object::DynamicProperty::Var)
+ continue;
+ int propertyType = 0;
+ int vmePropertyType = 0;
+ quint32 propertyFlags = 0;
- methodIndex++;
- }
- }
+ if (p->type < builtinTypeCount) {
+ propertyType = builtinTypes[p->type].metaType;
+ vmePropertyType = propertyType;
- // Now allocate properties
- for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
+ if (p->type == Object::DynamicProperty::Variant)
+ propertyFlags |= QQmlPropertyData::IsQVariant;
+ } else {
+ Q_ASSERT(p->type == Object::DynamicProperty::CustomList ||
+ p->type == Object::DynamicProperty::Custom);
- char *d = p->changedNameRef.data();
- p->name.writeUtf8(d);
- strcpy(d + p->name.utf8length(), "Changed");
- p->changedNameRef.loadByteArrayData();
+ QQmlType *qmltype = 0;
+ QString url;
+ if (!unit->imports().resolveType(p->customType.toString(), &qmltype, &url, 0, 0, 0))
+ COMPILE_EXCEPTION(p, tr("Invalid property type"));
- if (p->type == Object::DynamicProperty::Alias && !resolveAlias)
- continue;
+ if (!qmltype) {
+ QQmlTypeData *tdata = enginePrivate->typeLoader.getType(QUrl(url));
+ Q_ASSERT(tdata);
+ Q_ASSERT(tdata->isComplete());
- p->nameRef.load(p->name);
- }
+ QQmlCompiledData *data = tdata->compiledData();
- // Allocate default property if necessary
- if (defaultProperty)
- defPropRef.load("DefaultProperty");
+ if (p->type == Object::DynamicProperty::Custom) {
+ propertyType = data->metaTypeId;
+ vmePropertyType = QMetaType::QObjectStar;
+ } else {
+ propertyType = data->listMetaTypeId;
+ vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
+ }
- // Now allocate signals
- for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
+ tdata->release();
+ } else {
+ if (p->type == Object::DynamicProperty::Custom) {
+ propertyType = qmltype->typeId();
+ vmePropertyType = QMetaType::QObjectStar;
+ } else {
+ propertyType = qmltype->qListTypeId();
+ vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
+ }
+ }
- s->nameRef.load(s->name);
+ if (p->type == Object::DynamicProperty::Custom)
+ propertyFlags |= QQmlPropertyData::IsQObjectDerived;
+ else
+ propertyFlags |= QQmlPropertyData::IsQList;
+ }
- for (int jj = 0; jj < s->parameterNames.count(); ++jj)
- s->parameterNamesRef[jj].load(s->parameterNames.at(jj));
- }
+ if (!p->isReadOnly && p->type != Object::DynamicProperty::CustomList)
+ propertyFlags |= QQmlPropertyData::IsWritable;
- // Now allocate methods
- for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
- s->nameRef.load(s->name);
+ if (p->nameIndex != -1) {
+ QHashedCStringRef propertyName(cStringData + p->nameIndex, p->name.length(),
+ p->name.hash());
+ if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName.toUtf16();
+ cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
+ propertyType, effectiveMethodIndex);
+ } else {
+ QString propertyName = p->name.toString();
+ if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName;
+ cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
+ propertyType, effectiveMethodIndex);
+ }
- for (int jj = 0; jj < s->parameterNames.count(); ++jj)
- s->parameterNamesRef[jj].load(s->parameterNames.at(jj).constData());
- }
+ effectiveMethodIndex++;
- // Now allocate class name
- classNameRef.load(newClassName);
+ VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
+ (vmd->propertyData() + vmd->propertyCount)->propertyType = vmePropertyType;
+ vmd->propertyCount++;
+ }
- obj->metadata = builder.toData();
- builder.fromData(&obj->extObject, obj->metatype, obj->metadata);
+ // Now do var properties
+ for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p && varPropCount;
+ p = obj->dynamicProperties.next(p)) {
- if (mode == IgnoreAliases && aliasCount)
- compileState->aliasingObjects.append(obj);
+ if (p->type != Object::DynamicProperty::Var)
+ continue;
- obj->synthdata = dynamicData;
+ quint32 propertyFlags = QQmlPropertyData::IsVarProperty;
+ if (!p->isReadOnly)
+ propertyFlags |= QQmlPropertyData::IsWritable;
+
+ VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
+ (vmd->propertyData() + vmd->propertyCount)->propertyType = QMetaType::QVariant;
+ vmd->propertyCount++;
+ ((QQmlVMEMetaData *)dynamicData.data())->varPropertyCount++;
+
+ if (p->nameIndex != -1) {
+ QHashedCStringRef propertyName(cStringData + p->nameIndex, p->name.length(),
+ p->name.hash());
+ if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName.toUtf16();
+ cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
+ QMetaType::QVariant, effectiveMethodIndex);
+ } else {
+ QString propertyName = p->name.toString();
+ if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName;
+ cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
+ QMetaType::QVariant, effectiveMethodIndex);
+ }
- if (obj->synthCache) {
- obj->synthCache->release();
- obj->synthCache = 0;
+ effectiveMethodIndex++;
}
- if (obj->type != -1) {
- QQmlPropertyCache *superCache = output->types[obj->type].createPropertyCache(engine);
- QQmlPropertyCache *cache =
- superCache->copyAndAppend(engine, &obj->extObject,
- QQmlPropertyData::NoFlags,
- QQmlPropertyData::IsVMEFunction,
- QQmlPropertyData::IsVMESignal);
+ // Alias property count. Actual data is setup in buildDynamicMetaAliases
+ ((QQmlVMEMetaData *)dynamicData.data())->aliasCount = aliasCount;
+
+ // Dynamic slot data - comes after the property data
+ for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
+ int paramCount = s->parameterNames.count();
- // now we modify the flags appropriately for var properties.
- int propertyOffset = obj->extObject.propertyOffset();
- QQmlPropertyData *currPropData = 0;
- for (int pvi = firstPropertyVarIndex; pvi < totalPropCount; ++pvi) {
- currPropData = cache->property(pvi + propertyOffset);
- currPropData->setFlags(currPropData->getFlags() | QQmlPropertyData::IsVMEProperty);
+ QString funcScript;
+ int namesSize = 0;
+ if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1 /* commas */);
+ funcScript.reserve(strlen("(function ") + s->name.length() + 1 /* lparen */ +
+ namesSize + 1 /* rparen */ + s->body.length() + 1 /* rparen */);
+ funcScript = QLatin1String("(function ") + s->name.toString() + QLatin1Char('(');
+ for (int jj = 0; jj < paramCount; ++jj) {
+ if (jj) funcScript.append(QLatin1Char(','));
+ funcScript.append(QLatin1String(s->parameterNames.at(jj)));
}
+ funcScript += QLatin1Char(')') + s->body + QLatin1Char(')');
+
+ QByteArray utf8 = funcScript.toUtf8();
+ VMD::MethodData methodData = { s->parameterNames.count(),
+ dynamicData.size(),
+ utf8.length(),
+ s->location.start.line };
+
+ VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
+ VMD::MethodData &md = *(vmd->methodData() + vmd->methodCount);
+ vmd->methodCount++;
+ md = methodData;
- obj->synthCache = cache;
+ dynamicData.append((const char *)utf8.constData(), utf8.length());
}
+ if (aliasCount)
+ compileState->aliasingObjects.append(obj);
+
+ obj->synthdata = dynamicData;
+ obj->synthCache = cache;
+ obj->metatype = cache;
+
return true;
}
-bool QQmlCompiler::checkValidId(QQmlScript::Value *v, const QString &val)
+bool QQmlCompiler::buildDynamicMetaAliases(QQmlScript::Object *obj)
{
- if (val.isEmpty())
- COMPILE_EXCEPTION(v, tr( "Invalid empty ID"));
+ Q_ASSERT(obj->synthCache);
- QChar ch = val.at(0);
- if (ch.isLetter() && !ch.isLower())
- COMPILE_EXCEPTION(v, tr( "IDs cannot start with an uppercase letter"));
+ QByteArray &dynamicData = obj->synthdata;
- QChar u(QLatin1Char('_'));
- if (!ch.isLetter() && ch != u)
- COMPILE_EXCEPTION(v, tr( "IDs must start with a letter or underscore"));
+ QQmlPropertyCache *cache = obj->synthCache;
+ char *cStringData = cache->_dynamicStringData.data();
- for (int ii = 1; ii < val.count(); ++ii) {
- ch = val.at(ii);
- if (!ch.isLetterOrNumber() && ch != u)
- COMPILE_EXCEPTION(v, tr( "IDs must contain only letters, numbers, and underscores"));
- }
+ int effectiveMethodIndex = cache->methodIndexCacheStart + cache->propertyIndexCache.count();
+ int effectivePropertyIndex = cache->propertyIndexCacheStart + cache->propertyIndexCache.count();
+ int effectiveAliasIndex = 0;
- if (enginePrivate->v8engine()->illegalNames().contains(val))
- COMPILE_EXCEPTION(v, tr( "ID illegally masks global JavaScript property"));
+ for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
+ p = obj->dynamicProperties.next(p)) {
- return true;
-}
+ if (p->type != Object::DynamicProperty::Alias)
+ continue;
-#include <private/qqmljsparser_p.h>
+ if (!p->defaultValue)
+ COMPILE_EXCEPTION(obj, tr("No property alias location"));
-static QStringList astNodeToStringList(QQmlJS::AST::Node *node)
-{
- if (node->kind == QQmlJS::AST::Node::Kind_IdentifierExpression) {
- QString name =
- static_cast<QQmlJS::AST::IdentifierExpression *>(node)->name.toString();
- return QStringList() << name;
- } else if (node->kind == QQmlJS::AST::Node::Kind_FieldMemberExpression) {
- QQmlJS::AST::FieldMemberExpression *expr = static_cast<QQmlJS::AST::FieldMemberExpression *>(node);
+ if (!p->defaultValue->values.isOne() ||
+ p->defaultValue->values.first()->object ||
+ !p->defaultValue->values.first()->value.isScript())
+ COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias location"));
- QStringList rv = astNodeToStringList(expr->base);
- if (rv.isEmpty())
- return rv;
- rv.append(expr->name.toString());
- return rv;
- }
- return QStringList();
-}
+ QQmlJS::AST::Node *node = p->defaultValue->values.first()->value.asAST();
+ Q_ASSERT(node);
-bool QQmlCompiler::compileAlias(QFastMetaBuilder &builder,
- QByteArray &data,
- QQmlScript::Object *obj,
- int propIndex, int aliasIndex,
- Object::DynamicProperty &prop)
-{
- Q_ASSERT(!prop.nameRef.isEmpty());
- if (!prop.defaultValue)
- COMPILE_EXCEPTION(obj, tr("No property alias location"));
+ QStringList alias = astNodeToStringList(node);
+ if (alias.count() < 1 || alias.count() > 3)
+ COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
- if (!prop.defaultValue->values.isOne() ||
- prop.defaultValue->values.first()->object ||
- !prop.defaultValue->values.first()->value.isScript())
- COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
+ QQmlScript::Object *idObject = compileState->ids.value(alias.at(0));
+ if (!idObject)
+ COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias reference. Unable to find id \"%1\"").arg(alias.at(0)));
- QQmlJS::AST::Node *node = prop.defaultValue->values.first()->value.asAST();
- if (!node)
- COMPILE_EXCEPTION(obj, tr("No property alias location")); // ### Can this happen?
+ int propIdx = -1;
+ int notifySignal = -1;
+ int flags = 0;
+ int type = 0;
+ bool writable = false;
+ bool resettable = false;
- QStringList alias = astNodeToStringList(node);
+ quint32 propertyFlags = QQmlPropertyData::IsAlias;
- if (alias.count() < 1 || alias.count() > 3)
- COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
+ if (alias.count() == 2 || alias.count() == 3) {
+ QQmlPropertyData *property = this->property(idObject, alias.at(1));
- QQmlScript::Object *idObject = compileState->ids.value(alias.at(0));
- if (!idObject)
- COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. Unable to find id \"%1\"").arg(alias.at(0)));
+ if (!property || property->coreIndex > 0xFFFF)
+ COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias location"));
- QByteArray typeName;
+ propIdx = property->coreIndex;
+ type = property->propType;
- int propIdx = -1;
- int flags = 0;
- int type = 0;
- bool writable = false;
- bool resettable = false;
- if (alias.count() == 2 || alias.count() == 3) {
- propIdx = indexOfProperty(idObject, alias.at(1));
+ writable = property->isWritable();
+ resettable = property->isResettable();
+ notifySignal = property->notifyIndex;
- if (-1 == propIdx) {
- COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
- } else if (propIdx > 0xFFFF) {
- COMPILE_EXCEPTION(prop.defaultValue, tr("Alias property exceeds alias bounds"));
- }
+ if (alias.count() == 3) {
+ QQmlValueType *valueType = enginePrivate->valueTypes[type]; // XXX threadsafe?
+ if (!valueType)
+ COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias location"));
- QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx);
- if (!aliasProperty.isScriptable())
- COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
+ propIdx |= ((unsigned int)type) << 24;
+ int valueTypeIndex =
+ valueType->metaObject()->indexOfProperty(alias.at(2).toUtf8().constData());
+ if (valueTypeIndex == -1)
+ COMPILE_EXCEPTION(p->defaultValue, tr("Invalid alias location"));
+ Q_ASSERT(valueTypeIndex <= 0xFF);
- writable = aliasProperty.isWritable() && !prop.isReadOnly;
- resettable = aliasProperty.isResettable() && !prop.isReadOnly;
+ propIdx |= (valueTypeIndex << 16);
+ if (valueType->metaObject()->property(valueTypeIndex).isEnumType())
+ type = QVariant::Int;
+ else
+ type = valueType->metaObject()->property(valueTypeIndex).userType();
- type = aliasProperty.userType();
+ } else {
+ if (property->isEnum()) {
+ type = QVariant::Int;
+ } else {
+ // Copy type flags
+ propertyFlags |= property->getFlags() & QQmlPropertyData::PropTypeFlagMask;
- if (alias.count() == 3) {
- QQmlValueType *valueType = enginePrivate->valueTypes[aliasProperty.type()];
- if (!valueType)
- COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
+ if (property->isVarProperty())
+ propertyFlags |= QQmlPropertyData::IsQVariant;
- propIdx |= ((unsigned int)aliasProperty.type()) << 24;
+ if (property->isQObject())
+ flags |= QML_ALIAS_FLAG_PTR;
+ }
+ }
+ } else {
+ Q_ASSERT(idObject->type != -1); // How else did it get an id?
- int valueTypeIndex = valueType->metaObject()->indexOfProperty(alias.at(2).toUtf8().constData());
- if (valueTypeIndex == -1)
- COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
- Q_ASSERT(valueTypeIndex <= 0xFF);
-
- aliasProperty = valueType->metaObject()->property(valueTypeIndex);
- propIdx |= (valueTypeIndex << 16);
+ const QQmlCompiledData::TypeReference &ref = output->types.at(idObject->type);
+ if (ref.type)
+ type = ref.type->typeId();
+ else
+ type = ref.component->metaTypeId;
- // update the property type
- type = aliasProperty.userType();
+ flags |= QML_ALIAS_FLAG_PTR;
+ propertyFlags |= QQmlPropertyData::IsQObjectDerived;
}
- if (aliasProperty.isEnumType())
- typeName = "int"; // Avoid introducing a dependency on the aliased metaobject
- else
- typeName = aliasProperty.typeName();
- } else {
- Q_ASSERT(idObject->type != -1); // How else did it get an id?
+ QQmlVMEMetaData::AliasData aliasData = { idObject->idIndex, propIdx, flags, notifySignal };
+
+ typedef QQmlVMEMetaData VMD;
+ VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
+ *(vmd->aliasData() + effectiveAliasIndex++) = aliasData;
- const QQmlCompiledData::TypeReference &ref = output->types.at(idObject->type);
- if (ref.type)
- typeName = ref.type->typeName();
+ if (!p->isReadOnly && writable)
+ propertyFlags |= QQmlPropertyData::IsWritable;
else
- typeName = ref.component->root->className();
+ propertyFlags &= ~QQmlPropertyData::IsWritable;
- typeName += '*';
+ if (resettable)
+ propertyFlags |= QQmlPropertyData::IsResettable;
+ else
+ propertyFlags &= ~QQmlPropertyData::IsResettable;
+
+ if (p->nameIndex != -1) {
+ QHashedCStringRef propertyName(cStringData + p->nameIndex, p->name.length(),
+ p->name.hash());
+ if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName.toUtf16();
+ cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
+ type, effectiveMethodIndex++);
+ } else {
+ QString propertyName = p->name.toString();
+ if (p->isDefaultProperty) cache->_defaultPropertyName = propertyName;
+ cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
+ type, effectiveMethodIndex++);
+ }
}
- if (typeName.endsWith('*'))
- flags |= QML_ALIAS_FLAG_PTR;
+ return true;
+}
- if (type == QMetaType::UnknownType) {
- Q_ASSERT(!typeName.isEmpty());
- type = QMetaType::type(typeName);
- Q_ASSERT(type != QMetaType::UnknownType);
- Q_ASSERT(type != QMetaType::Void);
- }
+bool QQmlCompiler::checkValidId(QQmlScript::Value *v, const QString &val)
+{
+ if (val.isEmpty())
+ COMPILE_EXCEPTION(v, tr( "Invalid empty ID"));
- QQmlVMEMetaData::AliasData aliasData = { idObject->idIndex, propIdx, flags };
+ QChar ch = val.at(0);
+ if (ch.isLetter() && !ch.isLower())
+ COMPILE_EXCEPTION(v, tr( "IDs cannot start with an uppercase letter"));
- typedef QQmlVMEMetaData VMD;
- VMD *vmd = (QQmlVMEMetaData *)data.data();
- *(vmd->aliasData() + aliasIndex) = aliasData;
+ QChar u(QLatin1Char('_'));
+ if (!ch.isLetter() && ch != u)
+ COMPILE_EXCEPTION(v, tr( "IDs must start with a letter or underscore"));
- int propertyFlags = 0;
- if (writable)
- propertyFlags |= QFastMetaBuilder::Writable;
- if (resettable)
- propertyFlags |= QFastMetaBuilder::Resettable;
+ for (int ii = 1; ii < val.count(); ++ii) {
+ ch = val.at(ii);
+ if (!ch.isLetterOrNumber() && ch != u)
+ COMPILE_EXCEPTION(v, tr( "IDs must contain only letters, numbers, and underscores"));
+ }
- builder.setProperty(propIndex, prop.nameRef, type,
- (QFastMetaBuilder::PropertyFlag)propertyFlags,
- propIndex);
+ if (enginePrivate->v8engine()->illegalNames().contains(val))
+ COMPILE_EXCEPTION(v, tr( "ID illegally masks global JavaScript property"));
return true;
}
@@ -3336,7 +3311,7 @@ bool QQmlCompiler::buildBinding(QQmlScript::Value *value,
{
Q_ASSERT(prop->index != -1);
Q_ASSERT(prop->parent);
- Q_ASSERT(prop->parent->metaObject());
+ Q_ASSERT(prop->parent->metatype);
if (!prop->core.isWritable() && !prop->core.isQList() && !prop->isReadOnlyDeclaration)
COMPILE_EXCEPTION(prop, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
@@ -3546,8 +3521,7 @@ QQmlCompiler::genValueTypeData(QQmlScript::Property *valueTypeProp,
QQmlScript::Property *prop)
{
typedef QQmlPropertyPrivate QDPP;
- return QDPP::saveValueType(prop->parent->metaObject(), prop->index,
- enginePrivate->valueTypes[prop->type]->metaObject(),
+ return QDPP::saveValueType(prop->core, enginePrivate->valueTypes[prop->type]->metaObject(),
valueTypeProp->index, engine);
}
@@ -3558,7 +3532,7 @@ bool QQmlCompiler::completeComponentBuild()
for (Object *aliasObject = compileState->aliasingObjects.first(); aliasObject;
aliasObject = compileState->aliasingObjects.next(aliasObject))
- COMPILE_CHECK(buildDynamicMeta(aliasObject, ResolveAliases));
+ COMPILE_CHECK(buildDynamicMetaAliases(aliasObject));
QV4Compiler::Expression expr(unit->imports());
expr.component = compileState->root;
@@ -3733,13 +3707,13 @@ void QQmlCompiler::dumpStats()
*/
bool QQmlCompiler::canCoerce(int to, QQmlScript::Object *from)
{
- const QMetaObject *toMo = enginePrivate->rawMetaObjectForType(to);
- const QMetaObject *fromMo = from->metaObject();
+ QQmlPropertyCache *toMo = enginePrivate->rawPropertyCacheForType(to);
+ QQmlPropertyCache *fromMo = from->metatype;
while (fromMo) {
- if (QQmlPropertyPrivate::equal(fromMo, toMo))
+ if (fromMo == toMo)
return true;
- fromMo = fromMo->superClass();
+ fromMo = fromMo->parent();
}
return false;
}
@@ -3762,8 +3736,7 @@ QQmlType *QQmlCompiler::toQmlType(QQmlScript::Object *from)
if (from->type != -1 && output->types.at(from->type).type)
return output->types.at(from->type).type;
- // ### Optimize
- const QMetaObject *mo = from->metatype;
+ const QMetaObject *mo = from->metatype->firstCppMetaObject();
QQmlType *type = 0;
while (!type && mo) {
type = QQmlMetaType::qmlType(mo);
@@ -3774,7 +3747,7 @@ QQmlType *QQmlCompiler::toQmlType(QQmlScript::Object *from)
QStringList QQmlCompiler::deferredProperties(QQmlScript::Object *obj)
{
- const QMetaObject *mo = obj->metatype;
+ const QMetaObject *mo = obj->metatype->firstCppMetaObject();
int idx = mo->indexOfClassInfo("DeferredPropertyNames");
if (idx == -1)
@@ -3795,7 +3768,7 @@ QQmlCompiler::property(QQmlScript::Object *object, int index)
else if (object->type != -1)
cache = output->types[object->type].createPropertyCache(engine);
else
- cache = QQmlEnginePrivate::get(engine)->cache(object->metaObject());
+ cache = object->metatype;
return cache->property(index);
}
@@ -3812,7 +3785,7 @@ QQmlCompiler::property(QQmlScript::Object *object, const QHashedStringRef &name,
else if (object->type != -1)
cache = output->types[object->type].createPropertyCache(engine);
else
- cache = QQmlEnginePrivate::get(engine)->cache(object->metaObject());
+ cache = object->metatype;
QQmlPropertyData *d = cache->property(name);
@@ -3841,7 +3814,7 @@ QQmlCompiler::signal(QQmlScript::Object *object, const QHashedStringRef &name, b
else if (object->type != -1)
cache = output->types[object->type].createPropertyCache(engine);
else
- cache = QQmlEnginePrivate::get(engine)->cache(object->metaObject());
+ cache = object->metatype;
QQmlPropertyData *d = cache->property(name);
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index a326344336..c5d319c0f0 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -76,8 +76,7 @@ class QQmlComponent;
class QQmlContext;
class QQmlContextData;
-class Q_AUTOTEST_EXPORT QQmlCompiledData : public QQmlRefCount,
- public QQmlCleanup
+class Q_AUTOTEST_EXPORT QQmlCompiledData : public QQmlRefCount, public QQmlCleanup
{
public:
QQmlCompiledData(QQmlEngine *engine);
@@ -89,6 +88,10 @@ public:
QUrl url;
QQmlTypeNameCache *importCache;
+ int metaTypeId;
+ int listMetaTypeId;
+ bool isRegisteredWithEngine;
+
struct TypeReference
{
TypeReference()
@@ -98,7 +101,6 @@ public:
QQmlPropertyCache *typePropertyCache;
QQmlCompiledData *component;
- const QMetaObject *metaObject() const;
QQmlPropertyCache *propertyCache() const;
QQmlPropertyCache *createPropertyCache(QQmlEngine *);
};
@@ -115,8 +117,6 @@ public:
QList<V8Program> programs;
- const QMetaObject *root;
- QAbstractDynamicMetaObject rootData;
QQmlPropertyCache *rootPropertyCache;
QList<QString> primitives;
QList<QByteArray> datas;
@@ -161,8 +161,6 @@ private:
void dump(QQmlInstruction *, int idx = -1);
QQmlCompiledData(const QQmlCompiledData &other);
QQmlCompiledData &operator=(const QQmlCompiledData &other);
- QByteArray packData;
- int pack(const char *, size_t);
int indexForString(const QString &);
int indexForByteArray(const QByteArray &);
@@ -361,20 +359,16 @@ private:
QQmlScript::Object *obj,
QQmlScript::Value *value,
bool *isAssignment);
- enum DynamicMetaMode { IgnoreAliases, ResolveAliases, ForceCreation };
+ enum DynamicMetaMode { Normal, ForceCreation };
bool mergeDynamicMetaProperties(QQmlScript::Object *obj);
bool buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mode);
+ bool buildDynamicMetaAliases(QQmlScript::Object *obj);
bool checkDynamicMeta(QQmlScript::Object *obj);
bool buildBinding(QQmlScript::Value *, QQmlScript::Property *prop,
const QQmlCompilerTypes::BindingContext &ctxt);
bool buildLiteralBinding(QQmlScript::Value *, QQmlScript::Property *prop,
const QQmlCompilerTypes::BindingContext &ctxt);
bool buildComponentFromRoot(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
- bool compileAlias(QFastMetaBuilder &,
- QByteArray &data,
- QQmlScript::Object *obj,
- int propIndex, int aliasIndex,
- QQmlScript::Object::DynamicProperty &);
bool completeComponentBuild();
bool checkValidId(QQmlScript::Value *, const QString &);
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 352030d246..e3fc083914 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -441,6 +441,8 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
delete (*iter)->qobjectApi;
delete *iter;
}
+ for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
+ iter.value()->isRegisteredWithEngine = false;
}
void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
@@ -724,7 +726,7 @@ QQmlEngine::~QQmlEngine()
void QQmlEngine::clearComponentCache()
{
Q_D(QQmlEngine);
- d->clearCache();
+ d->typeLoader.clearCache();
}
/*!
@@ -742,7 +744,7 @@ void QQmlEngine::clearComponentCache()
void QQmlEngine::trimComponentCache()
{
Q_D(QQmlEngine);
- d->trimCache();
+ d->typeLoader.trimCache();
}
/*!
@@ -1403,7 +1405,7 @@ void QQmlData::clearBindingBit(int bit)
void QQmlData::setBindingBit(QObject *obj, int bit)
{
if (bindingBitsSize <= bit) {
- int props = obj->metaObject()->propertyCount();
+ int props = QQmlMetaObject(obj).propertyCount();
Q_ASSERT(bit < props);
int arraySize = (props + 31) / 32;
@@ -1878,33 +1880,59 @@ int QQmlEnginePrivate::listType(int t) const
return QQmlMetaType::listType(t);
}
-const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
+QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
{
Locker locker(this);
- QHash<int, const QMetaObject *>::ConstIterator iter = m_compositeTypes.find(t);
+ QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
if (iter != m_compositeTypes.end()) {
- return *iter;
+ return QQmlMetaObject((*iter)->rootPropertyCache);
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
- return type?type->baseMetaObject():0;
+ return QQmlMetaObject(type?type->baseMetaObject():0);
}
}
-const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
+QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
{
Locker locker(this);
- QHash<int, const QMetaObject *>::ConstIterator iter = m_compositeTypes.find(t);
+ QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
if (iter != m_compositeTypes.end()) {
- return *iter;
+ return QQmlMetaObject((*iter)->rootPropertyCache);
+ } else {
+ QQmlType *type = QQmlMetaType::qmlType(t);
+ return QQmlMetaObject(type?type->metaObject():0);
+ }
+}
+
+QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
+{
+ Locker locker(this);
+ QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
+ if (iter != m_compositeTypes.end()) {
+ return (*iter)->rootPropertyCache;
+ } else {
+ QQmlType *type = QQmlMetaType::qmlType(t);
+ locker.unlock();
+ return type?cache(type->metaObject()):0;
+ }
+}
+
+QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
+{
+ Locker locker(this);
+ QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
+ if (iter != m_compositeTypes.end()) {
+ return (*iter)->rootPropertyCache;
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
- return type?type->metaObject():0;
+ locker.unlock();
+ return type?cache(type->baseMetaObject()):0;
}
}
-void QQmlEnginePrivate::registerCompositeType(const QMetaObject *mo)
+void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
{
- QByteArray name = mo->className();
+ QByteArray name = data->rootPropertyCache->className();
QByteArray ptr = name + '*';
QByteArray lst = "QQmlListProperty<" + name + '>';
@@ -1916,7 +1944,7 @@ void QQmlEnginePrivate::registerCompositeType(const QMetaObject *mo)
qMetaTypeConstructHelper<QObject*>,
sizeof(QObject*),
static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
- mo);
+ 0);
int lst_type = QMetaType::registerNormalizedType(lst,
qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
@@ -1926,48 +1954,27 @@ void QQmlEnginePrivate::registerCompositeType(const QMetaObject *mo)
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;
+
Locker locker(this);
m_qmlLists.insert(lst_type, ptr_type);
- m_compositeTypes.insert(ptr_type, mo);
+ // The QQmlCompiledData is not referenced here, but it is removed from this
+ // hash in the QQmlCompiledData destructor
+ m_compositeTypes.insert(ptr_type, data);
}
-void QQmlEnginePrivate::unregisterCompositeType(const QMetaObject *mo)
+void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
{
- QByteArray name = mo->className();
-
- QByteArray ptr = name + '*';
- QByteArray lst = "QQmlListProperty<" + name + '>';
-
- int ptr_type = QMetaType::type(ptr.constData());
- int lst_type = QMetaType::type(lst.constData());
+ int ptr_type = data->metaTypeId;
+ int lst_type = data->listMetaTypeId;
Locker locker(this);
m_qmlLists.remove(lst_type);
m_compositeTypes.remove(ptr_type);
}
-void QQmlEnginePrivate::clearCache()
-{
- typeLoader.clearCache(this, &QQmlEnginePrivate::typeUnloaded);
-}
-
-void QQmlEnginePrivate::trimCache()
-{
- typeLoader.trimCache(this, &QQmlEnginePrivate::typeUnloaded);
-}
-
-void QQmlEnginePrivate::typeUnloaded(QQmlTypeData *typeData)
-{
- if (typeData && typeData->compiledData()) {
- const QMetaObject *mo = typeData->compiledData()->root;
- if (QQmlPropertyCache *pc = propertyCache.value(mo)) {
- propertyCache.remove(mo);
- pc->release();
- }
- unregisterCompositeType(mo);
- }
-}
-
bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
{
return typeLoader.isTypeLoaded(url);
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 8048e409f9..0631fe09ca 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -237,13 +237,12 @@ public:
QQmlMetaType::TypeCategory typeCategory(int) const;
bool isList(int) const;
int listType(int) const;
- const QMetaObject *rawMetaObjectForType(int) const;
- const QMetaObject *metaObjectForType(int) const;
- void registerCompositeType(const QMetaObject *);
- void unregisterCompositeType(const QMetaObject *);
-
- void clearCache();
- void trimCache();
+ QQmlMetaObject rawMetaObjectForType(int) const;
+ QQmlMetaObject metaObjectForType(int) const;
+ QQmlPropertyCache *propertyCacheForType(int);
+ QQmlPropertyCache *rawPropertyCacheForType(int);
+ void registerCompositeType(QQmlCompiledData *);
+ void unregisterCompositeType(QQmlCompiledData *);
bool isTypeLoaded(const QUrl &url) const;
bool isScriptLoaded(const QUrl &url) const;
@@ -302,15 +301,13 @@ private:
QQmlPropertyCache *createCache(const QMetaObject *);
QQmlPropertyCache *createCache(QQmlType *, int, QQmlError &error);
- void typeUnloaded(QQmlTypeData *typeData);
-
// These members must be protected by a QQmlEnginePrivate::Locker as they are required by
// the threaded loader. Only access them through their respective accessor methods.
QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *> moduleApiInstances;
QHash<const QMetaObject *, QQmlPropertyCache *> propertyCache;
QHash<QPair<QQmlType *, int>, QQmlPropertyCache *> typePropertyCache;
QHash<int, int> m_qmlLists;
- QHash<int, const QMetaObject *> m_compositeTypes;
+ QHash<int, QQmlCompiledData *> m_compositeTypes;
QHash<QUrl, QByteArray> debugChangesHash;
// These members is protected by the full QQmlEnginePrivate::mutex mutex
diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index 6e233c9fae..3ed7286ed9 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -44,6 +44,7 @@
#include <private/qtqmlglobal_p.h>
#include <QtCore/QObject>
+#include <private/qqmlpropertycache_p.h>
QT_BEGIN_HEADER
@@ -63,32 +64,105 @@ QT_BEGIN_NAMESPACE
return status == Yes; \
}
-#define FAST_CONNECT(Sender, Signal, Receiver, Method) \
+/*!
+ Connect \a Signal of \a Sender to \a Method of \a Receiver. \a Signal must be
+ of type \a SenderType and \a Receiver of type \a ReceiverType.
+
+ Unlike QObject::connect(), this method caches the lookup of the signal and method
+ indexes. It also does not require lazy QMetaObjects to be built so should be
+ preferred in all QML code that might interact with QML built objects.
+
+ \code
+ QQuickTextControl *control;
+ QQuickTextEdit *textEdit;
+ qmlobject_connect(control, QQuickTextControl, SIGNAL(updateRequest(QRectF)),
+ textEdit, QQuickTextEdit, SLOT(updateDocument()));
+ \endcode
+*/
+#define qmlobject_connect(Sender, SenderType, Signal, Receiver, ReceiverType, Method) \
{ \
- QObject *sender = (Sender); \
- QObject *receiver = (Receiver); \
+ SenderType *sender = (Sender); \
+ ReceiverType *receiver = (Receiver); \
const char *signal = (Signal); \
const char *method = (Method); \
static int signalIdx = -1; \
static int methodIdx = -1; \
if (signalIdx < 0) { \
- if (((int)(*signal) - '0') == QSIGNAL_CODE) \
- signalIdx = sender->metaObject()->indexOfSignal(signal+1); \
- else \
- qWarning("FAST_CONNECT: Invalid signal %s. Please make sure you are using the SIGNAL macro.", signal); \
+ Q_ASSERT(((int)(*signal) - '0') == QSIGNAL_CODE); \
+ signalIdx = SenderType::staticMetaObject.indexOfSignal(signal+1); \
} \
if (methodIdx < 0) { \
int code = ((int)(*method) - '0'); \
+ Q_ASSERT(code == QSLOT_CODE || code == QSIGNAL_CODE); \
if (code == QSLOT_CODE) \
- methodIdx = receiver->metaObject()->indexOfSlot(method+1); \
- else if (code == QSIGNAL_CODE) \
- methodIdx = receiver->metaObject()->indexOfSignal(method+1); \
+ methodIdx = ReceiverType::staticMetaObject.indexOfSlot(method+1); \
else \
- qWarning("FAST_CONNECT: Invalid method %s. Please make sure you are using the SIGNAL or SLOT macro.", method); \
+ methodIdx = ReceiverType::staticMetaObject.indexOfSignal(method+1); \
} \
+ Q_ASSERT(signalIdx != -1 && methodIdx != -1); \
QMetaObject::connect(sender, signalIdx, receiver, methodIdx, Qt::DirectConnection); \
}
+/*!
+ Disconnect \a Signal of \a Sender from \a Method of \a Receiver. \a Signal must be
+ of type \a SenderType and \a Receiver of type \a ReceiverType.
+
+ Unlike QObject::disconnect(), this method caches the lookup of the signal and method
+ indexes. It also does not require lazy QMetaObjects to be built so should be
+ preferred in all QML code that might interact with QML built objects.
+
+ \code
+ QQuickTextControl *control;
+ QQuickTextEdit *textEdit;
+ qmlobject_disconnect(control, QQuickTextControl, SIGNAL(updateRequest(QRectF)),
+ textEdit, QQuickTextEdit, SLOT(updateDocument()));
+ \endcode
+*/
+#define qmlobject_disconnect(Sender, SenderType, Signal, Receiver, ReceiverType, Method) \
+{ \
+ SenderType *sender = (Sender); \
+ ReceiverType *receiver = (Receiver); \
+ const char *signal = (Signal); \
+ const char *method = (Method); \
+ static int signalIdx = -1; \
+ static int methodIdx = -1; \
+ if (signalIdx < 0) { \
+ Q_ASSERT(((int)(*signal) - '0') == QSIGNAL_CODE); \
+ signalIdx = SenderType::staticMetaObject.indexOfSignal(signal+1); \
+ } \
+ if (methodIdx < 0) { \
+ int code = ((int)(*method) - '0'); \
+ Q_ASSERT(code == QSLOT_CODE || code == QSIGNAL_CODE); \
+ if (code == QSLOT_CODE) \
+ methodIdx = ReceiverType::staticMetaObject.indexOfSlot(method+1); \
+ else \
+ methodIdx = ReceiverType::staticMetaObject.indexOfSignal(method+1); \
+ } \
+ Q_ASSERT(signalIdx != -1 && methodIdx != -1); \
+ QMetaObject::disconnect(sender, signalIdx, receiver, methodIdx); \
+}
+
+/*!
+ This method is identical to qobject_cast<T>() except that it does not require lazy
+ QMetaObjects to be built, so should be preferred in all QML code that might interact
+ with QML built objects.
+
+ \code
+ QObject *object;
+ if (QQuickTextEdit *textEdit = qmlobject_cast<QQuickTextEdit *>(object)) {
+ // ...Do something...
+ }
+ \endcode
+*/
+template<class T>
+T qmlobject_cast(QObject *object)
+{
+ if (QQmlMetaObject::canConvert(object, &reinterpret_cast<T>(object)->staticMetaObject))
+ return static_cast<T>(object);
+ else
+ return 0;
+}
+
bool Q_QML_PRIVATE_EXPORT QQml_isSignalConnected(QObject*, int, int);
#define IS_SIGNAL_CONNECTED(Sender, Signal) \
diff --git a/src/qml/qml/qqmlinstruction.cpp b/src/qml/qml/qqmlinstruction.cpp
index 5715d7afb2..da5e9aa401 100644
--- a/src/qml/qml/qqmlinstruction.cpp
+++ b/src/qml/qml/qqmlinstruction.cpp
@@ -85,7 +85,7 @@ void QQmlCompiledData::dump(QQmlInstruction *instr, int idx)
qWarning().nospace() << idx << "\t\t" << "CREATE_COMPONENT\t" << instr->createComponent.count;
break;
case QQmlInstruction::StoreMetaObject:
- qWarning().nospace() << idx << "\t\t" << "STORE_META\t\t" << instr->storeMeta.data;
+ qWarning().nospace() << idx << "\t\t" << "STORE_META\t\t";
break;
case QQmlInstruction::StoreFloat:
qWarning().nospace() << idx << "\t\t" << "STORE_FLOAT\t\t" << instr->storeFloat.propertyIndex << "\t" << instr->storeFloat.value;
diff --git a/src/qml/qml/qqmlinstruction_p.h b/src/qml/qml/qqmlinstruction_p.h
index 04f419d9d5..bd279d66d8 100644
--- a/src/qml/qml/qqmlinstruction_p.h
+++ b/src/qml/qml/qqmlinstruction_p.h
@@ -211,7 +211,6 @@ union QQmlInstruction
};
struct instr_storeMeta {
QML_INSTR_HEADER
- int data;
int aliasData;
int propertyCache;
};
diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp
index c3537dac9d..14425f22e5 100644
--- a/src/qml/qml/qqmllist.cpp
+++ b/src/qml/qml/qqmllist.cpp
@@ -64,7 +64,7 @@ QQmlListReference QQmlListReferencePrivate::init(const QQmlListProperty<QObject>
rv.d = new QQmlListReferencePrivate;
rv.d->object = prop.object;
- rv.d->elementType = p?p->rawMetaObjectForType(listType):QQmlMetaType::qmlType(listType)->baseMetaObject();
+ rv.d->elementType = QQmlPropertyPrivate::rawMetaObjectForType(p, listType);
rv.d->property = prop;
rv.d->propertyType = propType;
@@ -205,7 +205,7 @@ to a list.
*/
const QMetaObject *QQmlListReference::listElementType() const
{
- if (isValid()) return d->elementType;
+ if (isValid()) return d->elementType.metaObject();
else return 0;
}
@@ -262,7 +262,7 @@ bool QQmlListReference::append(QObject *object) const
{
if (!canAppend()) return false;
- if (object && !QQmlPropertyPrivate::canConvert(object->metaObject(), d->elementType))
+ if (object && !QQmlMetaObject::canConvert(object, d->elementType))
return false;
d->property.append(&d->property, object);
diff --git a/src/qml/qml/qqmllist_p.h b/src/qml/qml/qqmllist_p.h
index 0fe0ed3d44..e9a613a181 100644
--- a/src/qml/qml/qqmllist_p.h
+++ b/src/qml/qml/qqmllist_p.h
@@ -55,6 +55,7 @@
#include "qqmllist.h"
#include "qqmlguard_p.h"
+#include "qqmlpropertycache_p.h"
QT_BEGIN_NAMESPACE
@@ -66,7 +67,7 @@ public:
static QQmlListReference init(const QQmlListProperty<QObject> &, int, QQmlEngine *);
QQmlGuard<QObject> object;
- const QMetaObject *elementType;
+ QQmlMetaObject elementType;
QQmlListProperty<QObject> property;
int propertyType;
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 087fbaa9bf..7af7848ddb 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -337,11 +337,44 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
QString signalName = terminal.mid(2);
signalName[0] = signalName.at(0).toLower();
- QMetaMethod method = findSignalByName(currentObject->metaObject(), signalName.toLatin1().constData());
- if (method.isValid()) {
- object = currentObject;
- core.load(method);
- return;
+ // XXX - this code treats methods as signals
+
+ QQmlData *ddata = QQmlData::get(currentObject, false);
+ if (ddata && ddata->propertyCache) {
+
+ // Try method
+ QQmlPropertyData *d = ddata->propertyCache->property(signalName);
+ while (d && !d->isFunction())
+ d = ddata->propertyCache->overrideData(d);
+
+ if (d) {
+ object = currentObject;
+ core = *d;
+ return;
+ }
+
+ // Try property
+ if (signalName.endsWith(QLatin1String("Changed"))) {
+ QString propName = signalName.mid(0, signalName.length() - 7);
+ QQmlPropertyData *d = ddata->propertyCache->property(propName);
+ while (d && d->isFunction())
+ d = ddata->propertyCache->overrideData(d);
+
+ if (d && d->notifyIndex != -1) {
+ object = currentObject;
+ core = *ddata->propertyCache->method(d->notifyIndex);
+ return;
+ }
+ }
+
+ } else {
+ QMetaMethod method = findSignalByName(currentObject->metaObject(),
+ signalName.toLatin1().constData());
+ if (method.isValid()) {
+ object = currentObject;
+ core.load(method);
+ return;
+ }
}
}
@@ -735,8 +768,7 @@ QQmlPropertyPrivate::binding(QObject *object, int coreIndex, int valueTypeIndex)
QQmlPropertyData *propertyData =
data->propertyCache?data->propertyCache->property(coreIndex):0;
if (propertyData && propertyData->isAlias()) {
- const QQmlVMEMetaObject *vme =
- static_cast<const QQmlVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex));
+ QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex) || aCoreIndex == -1)
@@ -777,8 +809,8 @@ void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex,
QQmlPropertyData *propertyData =
data->propertyCache?data->propertyCache->property(coreIndex):0;
if (propertyData && propertyData->isAlias()) {
- const QQmlVMEMetaObject *vme =
- static_cast<const QQmlVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex));
+ QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
+
QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
if (vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) {
// This will either be a value type sub-reference or an alias to a value-type sub-reference not both
@@ -811,8 +843,7 @@ QQmlPropertyPrivate::setBinding(QObject *object, int coreIndex, int valueTypeInd
QQmlPropertyData *propertyData =
data->propertyCache?data->propertyCache->property(coreIndex):0;
if (propertyData && propertyData->isAlias()) {
- const QQmlVMEMetaObject *vme =
- static_cast<const QQmlVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex));
+ QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) {
@@ -871,8 +902,7 @@ QQmlPropertyPrivate::setBindingNoEnable(QObject *object, int coreIndex, int valu
QQmlPropertyData *propertyData =
data->propertyCache?data->propertyCache->property(coreIndex):0;
if (propertyData && propertyData->isAlias()) {
- const QQmlVMEMetaObject *vme =
- static_cast<const QQmlVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex));
+ QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) {
@@ -988,7 +1018,7 @@ QQmlPropertyPrivate::takeSignalExpression(const QQmlProperty &that,
return signalHandler->takeExpression(expr);
if (expr) {
- QQmlBoundSignal *signal = new QQmlBoundSignal(that.d->object, that.method(), that.d->object,
+ QQmlBoundSignal *signal = new QQmlBoundSignal(that.d->object, that.index(), that.d->object,
expr->context()->engine);
signal->takeExpression(expr);
}
@@ -1096,8 +1126,23 @@ QVariant QQmlPropertyPrivate::readValueProperty()
} else {
- return object->metaObject()->property(core.coreIndex).read(object.data());
+ 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) {
+ args[0] = &value;
+ } else {
+ 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]);
+ return value;
}
}
@@ -1293,34 +1338,33 @@ bool QQmlPropertyPrivate::write(QObject *object,
} else if (property.isQObject()) {
- const QMetaObject *valMo = rawMetaObjectForType(enginePriv, value.userType());
+ QQmlMetaObject valMo = rawMetaObjectForType(enginePriv, value.userType());
- if (!valMo)
+ if (valMo.isNull())
return false;
QObject *o = *(QObject **)value.constData();
- const QMetaObject *propMo = rawMetaObjectForType(enginePriv, propertyType);
+ QQmlMetaObject propMo = rawMetaObjectForType(enginePriv, propertyType);
- if (o) valMo = o->metaObject();
+ if (o) valMo = o;
- if (canConvert(valMo, propMo)) {
+ if (QQmlMetaObject::canConvert(valMo, propMo)) {
void *args[] = { &o, 0, &status, &flags };
- QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx,
- args);
- } else if (!o && canConvert(propMo, valMo)) {
+ 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);
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, args);
} else {
return false;
}
} else if (property.isQList()) {
- const QMetaObject *listType = 0;
+ QQmlMetaObject listType;
+
if (enginePriv) {
listType = enginePriv->rawMetaObjectForType(enginePriv->listType(property.propType));
} else {
@@ -1328,7 +1372,7 @@ bool QQmlPropertyPrivate::write(QObject *object,
if (!type) return false;
listType = type->baseMetaObject();
}
- if (!listType) return false;
+ if (listType.isNull()) return false;
QQmlListProperty<void> prop;
void *args[] = { &prop, 0 };
@@ -1343,7 +1387,7 @@ bool QQmlPropertyPrivate::write(QObject *object,
for (int ii = 0; ii < qdlr.count(); ++ii) {
QObject *o = qdlr.at(ii);
- if (o && !canConvert(o->metaObject(), listType))
+ if (o && !QQmlMetaObject::canConvert(o, listType))
o = 0;
prop.append(&prop, (void *)o);
}
@@ -1352,13 +1396,13 @@ bool QQmlPropertyPrivate::write(QObject *object,
for (int ii = 0; ii < list.count(); ++ii) {
QObject *o = list.at(ii);
- if (o && !canConvert(o->metaObject(), listType))
+ if (o && !QQmlMetaObject::canConvert(o, listType))
o = 0;
prop.append(&prop, (void *)o);
}
} else {
QObject *o = enginePriv?enginePriv->toQObject(value):QQmlMetaType::toQObject(value);
- if (o && !canConvert(o->metaObject(), listType))
+ if (o && !QQmlMetaObject::canConvert(o, listType))
o = 0;
prop.append(&prop, (void *)o);
}
@@ -1481,7 +1525,7 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
QQmlJavaScriptExpression::DeleteWatcher watcher(expression);
QVariant value;
- bool isVmeProperty = core.isVMEProperty();
+ bool isVarProperty = core.isVarProperty();
if (isUndefined) {
} else if (core.isQList()) {
@@ -1490,13 +1534,13 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
value = QVariant::fromValue((QObject *)0);
} else if (core.propType == qMetaTypeId<QList<QUrl> >()) {
value = resolvedUrlSequence(v8engine->toVariant(result, qMetaTypeId<QList<QUrl> >()), context);
- } else if (!isVmeProperty && type != qMetaTypeId<QJSValue>()) {
+ } else if (!isVarProperty && type != qMetaTypeId<QJSValue>()) {
value = v8engine->toVariant(result, type);
}
if (expression->hasError()) {
return false;
- } else if (isVmeProperty) {
+ } else if (isVarProperty) {
if (!result.IsEmpty() && result->IsFunction()
&& !result->ToObject()->GetHiddenValue(v8engine->bindingFlagKey()).IsEmpty()) {
// we explicitly disallow this case to avoid confusion. Users can still store one
@@ -1504,6 +1548,8 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
expression->delayedError()->error.setDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
return false;
}
+
+ typedef QQmlVMEMetaObject VMEMO;
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
vmemo->setVMEProperty(core.coreIndex, result);
@@ -1540,9 +1586,9 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
if (QObject *o = *(QObject **)value.constData()) {
valueType = o->metaObject()->className();
- if (const QMetaObject *propertyMetaObject = rawMetaObjectForType(QQmlEnginePrivate::get(engine), type)) {
- propertyType = propertyMetaObject->className();
- }
+ QQmlMetaObject propertyMetaObject = rawMetaObjectForType(QQmlEnginePrivate::get(engine), type);
+ if (!propertyMetaObject.isNull())
+ propertyType = propertyMetaObject.className();
}
} else if (value.userType() != QVariant::Invalid) {
valueType = QMetaType::typeName(value.userType());
@@ -1563,13 +1609,13 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
return true;
}
-const QMetaObject *QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engine, int userType)
+QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engine, int userType)
{
if (engine) {
return engine->rawMetaObjectForType(userType);
} else {
QQmlType *type = QQmlMetaType::qmlType(userType);
- return type?type->baseMetaObject():0;
+ return QQmlMetaObject(type?type->baseMetaObject():0);
}
}
@@ -1762,14 +1808,13 @@ int QQmlPropertyPrivate::bindingIndex(const QQmlPropertyData &that)
}
QQmlPropertyData
-QQmlPropertyPrivate::saveValueType(const QMetaObject *metaObject, int index,
- const QMetaObject *subObject, int subIndex,
- QQmlEngine *)
+QQmlPropertyPrivate::saveValueType(const QQmlPropertyData &base,
+ const QMetaObject *subObject, int subIndex,
+ QQmlEngine *)
{
QMetaProperty subProp = subObject->property(subIndex);
- QQmlPropertyData core;
- core.load(metaObject->property(index));
+ QQmlPropertyData core = base;
core.setFlags(core.getFlags() | QQmlPropertyData::IsValueTypeVirtual);
core.valueTypeFlags = QQmlPropertyData::flagsForProperty(subProp);
core.valueTypeCoreIndex = subIndex;
@@ -1795,31 +1840,6 @@ QQmlPropertyPrivate::restore(QObject *object, const QQmlPropertyData &data,
}
/*!
- Returns true if lhs and rhs refer to the same metaobject data
-*/
-bool QQmlPropertyPrivate::equal(const QMetaObject *lhs, const QMetaObject *rhs)
-{
- return lhs == rhs || (1 && lhs && rhs && lhs->d.stringdata == rhs->d.stringdata);
-}
-
-/*!
- Returns true if from inherits to.
-*/
-bool QQmlPropertyPrivate::canConvert(const QMetaObject *from, const QMetaObject *to)
-{
- if (from && to == &QObject::staticMetaObject)
- return true;
-
- while (from) {
- if (equal(from, to))
- return true;
- from = from->superClass();
- }
-
- return false;
-}
-
-/*!
Return the signal corresponding to \a name
*/
QMetaMethod QQmlPropertyPrivate::findSignalByName(const QMetaObject *mo, const QByteArray &name)
@@ -1883,17 +1903,8 @@ static inline void flush_vme_signal(const QObject *object, int index)
QQmlPropertyData *property = data->propertyCache->method(index);
if (property && property->isVMESignal()) {
- const QMetaObject *metaObject = object->metaObject();
- int methodOffset = metaObject->methodOffset();
-
- while (methodOffset > index) {
- metaObject = metaObject->d.superdata;
- methodOffset -= QMetaObject_methods(metaObject);
- }
-
- QQmlVMEMetaObject *vme =
- static_cast<QQmlVMEMetaObject *>(const_cast<QMetaObject *>(metaObject));
-
+ QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForMethod(const_cast<QObject *>(object),
+ index);
vme->connectAliasSignal(index);
}
}
@@ -1921,19 +1932,4 @@ void QQmlPropertyPrivate::flushSignal(const QObject *sender, int signal_index)
flush_vme_signal(sender, signal_index);
}
-/*!
-Return \a metaObject's [super] meta object that provides data for \a property.
-*/
-const QMetaObject *QQmlPropertyPrivate::metaObjectForProperty(const QMetaObject *metaObject, int property)
-{
- int propertyOffset = metaObject->propertyOffset();
-
- while (propertyOffset > property) {
- metaObject = metaObject->d.superdata;
- propertyOffset -= QMetaObject_properties(metaObject);
- }
-
- return metaObject;
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h
index cba7849ea0..4f0db342c2 100644
--- a/src/qml/qml/qqmlproperty_p.h
+++ b/src/qml/qml/qqmlproperty_p.h
@@ -101,7 +101,7 @@ public:
QVariant readValueProperty();
bool writeValueProperty(const QVariant &, WriteFlags);
- static const QMetaObject *rawMetaObjectForType(QQmlEnginePrivate *, int);
+ static QQmlMetaObject rawMetaObjectForType(QQmlEnginePrivate *, int);
static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object,
const QVariant &value, int flags);
static bool writeValueProperty(QObject *, QQmlEngine *,
@@ -122,15 +122,13 @@ public:
static QQmlAbstractBinding *binding(QObject *, int coreIndex,
int valueTypeIndex /* -1 */);
- static QQmlPropertyData saveValueType(const QMetaObject *, int,
- const QMetaObject *, int,
- QQmlEngine *);
+ static QQmlPropertyData saveValueType(const QQmlPropertyData &,
+ const QMetaObject *, int,
+ QQmlEngine *);
static QQmlProperty restore(QObject *,
const QQmlPropertyData &,
QQmlContextData *);
- static bool equal(const QMetaObject *, const QMetaObject *);
- static bool canConvert(const QMetaObject *from, const QMetaObject *to);
static inline QQmlPropertyPrivate *get(const QQmlProperty &p) {
return p.d;
}
@@ -158,7 +156,6 @@ public:
static bool connect(const QObject *sender, int signal_index,
const QObject *receiver, int method_index,
int type = 0, int *types = 0);
- static const QMetaObject *metaObjectForProperty(const QMetaObject *, int);
static void flushSignal(const QObject *sender, int signal_index);
};
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 491629bc0a..86c0d715af 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -47,6 +47,7 @@
#include <private/qmetaobject_p.h>
#include <private/qqmlaccessors_p.h>
+#include <private/qmetaobjectbuilder_p.h>
#include <QtCore/qdebug.h>
@@ -68,6 +69,8 @@ class QQmlPropertyCacheMethodArguments
{
public:
QQmlPropertyCacheMethodArguments *next;
+
+ QList<QByteArray> *names;
int arguments[0];
};
@@ -190,6 +193,9 @@ void QQmlPropertyData::load(const QMetaMethod &m)
}
}
+ if (m.attributes() & QMetaMethod::Cloned)
+ flags |= IsCloned;
+
Q_ASSERT(m.revision() <= Q_INT16_MAX);
revision = m.revision();
}
@@ -217,6 +223,9 @@ void QQmlPropertyData::lazyLoad(const QMetaMethod &m)
}
}
+ if (m.attributes() & QMetaMethod::Cloned)
+ flags |= IsCloned;
+
Q_ASSERT(m.revision() <= Q_INT16_MAX);
revision = m.revision();
}
@@ -225,8 +234,8 @@ void QQmlPropertyData::lazyLoad(const QMetaMethod &m)
Creates a new empty QQmlPropertyCache.
*/
QQmlPropertyCache::QQmlPropertyCache(QQmlEngine *e)
-: engine(e), parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
- signalHanderIndexCacheStart(0), metaObject(0), argumentsCache(0)
+: engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
+ signalHandlerIndexCacheStart(0), _ownMetaObject(false), _metaObject(0), argumentsCache(0)
{
Q_ASSERT(engine);
}
@@ -235,8 +244,8 @@ QQmlPropertyCache::QQmlPropertyCache(QQmlEngine *e)
Creates a new QQmlPropertyCache of \a metaObject.
*/
QQmlPropertyCache::QQmlPropertyCache(QQmlEngine *e, const QMetaObject *metaObject)
-: engine(e), parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
- signalHanderIndexCacheStart(0), metaObject(0), argumentsCache(0)
+: engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
+ signalHandlerIndexCacheStart(0), _ownMetaObject(false), _metaObject(0), argumentsCache(0)
{
Q_ASSERT(engine);
Q_ASSERT(metaObject);
@@ -251,6 +260,7 @@ QQmlPropertyCache::~QQmlPropertyCache()
QQmlPropertyCacheMethodArguments *args = argumentsCache;
while (args) {
QQmlPropertyCacheMethodArguments *next = args->next;
+ if (args->names) delete args->names;
free(args);
args = next;
}
@@ -258,8 +268,11 @@ QQmlPropertyCache::~QQmlPropertyCache()
// We must clear this prior to releasing the parent incase it is a
// linked hash
stringCache.clear();
- if (parent) parent->release();
- parent = 0;
+ if (_parent) _parent->release();
+
+ if (_ownMetaObject) free((void *)_metaObject);
+ _metaObject = 0;
+ _parent = 0;
engine = 0;
}
@@ -283,14 +296,15 @@ void QQmlPropertyCache::clear()
QQmlPropertyCache *QQmlPropertyCache::copy(int reserve)
{
QQmlPropertyCache *cache = new QQmlPropertyCache(engine);
- cache->parent = this;
- cache->parent->addref();
+ cache->_parent = this;
+ cache->_parent->addref();
cache->propertyIndexCacheStart = propertyIndexCache.count() + propertyIndexCacheStart;
cache->methodIndexCacheStart = methodIndexCache.count() + methodIndexCacheStart;
- cache->signalHanderIndexCacheStart = signalHandlerIndexCache.count() + signalHanderIndexCacheStart;
+ cache->signalHandlerIndexCacheStart = signalHandlerIndexCache.count() + signalHandlerIndexCacheStart;
cache->stringCache.linkAndReserve(stringCache, reserve);
cache->allowedRevisionCache = allowedRevisionCache;
- cache->metaObject = metaObject;
+ cache->_metaObject = _metaObject;
+ cache->_defaultPropertyName = _defaultPropertyName;
// We specifically do *NOT* copy the constructor
@@ -302,6 +316,247 @@ QQmlPropertyCache *QQmlPropertyCache::copy()
return copy(0);
}
+QQmlPropertyCache *QQmlPropertyCache::copyAndReserve(QQmlEngine *, int propertyCount, int methodCount,
+ int signalCount)
+{
+ QQmlPropertyCache *rv = copy(propertyCount + methodCount + signalCount);
+ rv->propertyIndexCache.reserve(propertyCount);
+ rv->methodIndexCache.reserve(methodCount);
+ rv->signalHandlerIndexCache.reserve(signalCount);
+ rv->_metaObject = 0;
+
+ return rv;
+}
+
+void QQmlPropertyCache::appendProperty(const QString &name,
+ quint32 flags, int coreIndex, int propType, int notifyIndex)
+{
+ QQmlPropertyData data;
+ data.propType = propType;
+ data.coreIndex = coreIndex;
+ data.notifyIndex = notifyIndex;
+ data.flags = flags;
+
+ QHashedString string(name);
+ if (QQmlPropertyData **old = stringCache.value(string)) {
+ data.overrideIndexIsProperty = !(*old)->isFunction();
+ data.overrideIndex = (*old)->coreIndex;
+ }
+
+ propertyIndexCache.append(data);
+
+ stringCache.insert(string, propertyIndexCache.data() + propertyIndexCache.count() - 1);
+}
+
+void QQmlPropertyCache::appendProperty(const QHashedCStringRef &name,
+ quint32 flags, int coreIndex, int propType, int notifyIndex)
+{
+ QQmlPropertyData data;
+ data.propType = propType;
+ data.coreIndex = coreIndex;
+ data.notifyIndex = notifyIndex;
+ data.flags = flags;
+
+ if (QQmlPropertyData **old = stringCache.value(name)) {
+ data.overrideIndexIsProperty = !(*old)->isFunction();
+ data.overrideIndex = (*old)->coreIndex;
+ }
+
+ propertyIndexCache.append(data);
+
+ stringCache.insert(name, propertyIndexCache.data() + propertyIndexCache.count() - 1);
+}
+
+void QQmlPropertyCache::appendSignal(const QString &name, quint32 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;
+
+ QQmlPropertyData handler = data;
+ handler.flags |= QQmlPropertyData::IsSignalHandler;
+
+ if (types) {
+ int argumentCount = *types;
+ typedef QQmlPropertyCacheMethodArguments A;
+ A *args = static_cast<A *>(malloc(sizeof(A) + (argumentCount + 1) * sizeof(int)));
+ ::memcpy(args->arguments, types, (argumentCount + 1) * sizeof(int));
+ args->names = new QList<QByteArray>(names);
+ args->next = argumentsCache;
+ argumentsCache = args;
+ data.arguments = args;
+ }
+
+ QString handlerName = QLatin1String("on") + name;
+ handlerName[2] = handlerName[2].toUpper();
+
+ QHashedString string(name);
+ if (QQmlPropertyData **old = stringCache.value(string)) {
+ data.overrideIndexIsProperty = !(*old)->isFunction();
+ data.overrideIndex = (*old)->coreIndex;
+ }
+
+ methodIndexCache.append(data);
+ signalHandlerIndexCache.append(handler);
+
+ stringCache.insert(string, methodIndexCache.data() + methodIndexCache.count() - 1);
+ stringCache.insert(handlerName, signalHandlerIndexCache.data() + signalHandlerIndexCache.count() - 1);
+}
+
+void QQmlPropertyCache::appendSignal(const QHashedCStringRef &name, quint32 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;
+
+ QQmlPropertyData handler = data;
+ handler.flags |= QQmlPropertyData::IsSignalHandler;
+
+ if (types) {
+ int argumentCount = *types;
+ typedef QQmlPropertyCacheMethodArguments A;
+ A *args = static_cast<A *>(malloc(sizeof(A) + (argumentCount + 1) * sizeof(int)));
+ ::memcpy(args->arguments, types, (argumentCount + 1) * sizeof(int));
+ args->names = new QList<QByteArray>(names);
+ args->next = argumentsCache;
+ argumentsCache = args;
+ data.arguments = args;
+ }
+
+ QString handlerName = QLatin1String("on") + name.toUtf16();
+ handlerName[2] = handlerName[2].toUpper();
+
+ if (QQmlPropertyData **old = stringCache.value(name)) {
+ data.overrideIndexIsProperty = !(*old)->isFunction();
+ data.overrideIndex = (*old)->coreIndex;
+ }
+
+ methodIndexCache.append(data);
+ signalHandlerIndexCache.append(handler);
+
+ stringCache.insert(name, methodIndexCache.data() + methodIndexCache.count() - 1);
+ stringCache.insert(handlerName, signalHandlerIndexCache.data() + signalHandlerIndexCache.count() - 1);
+}
+
+void QQmlPropertyCache::appendMethod(const QString &name, quint32 flags, int coreIndex,
+ const QList<QByteArray> &names)
+{
+ int argumentCount = names.count();
+
+ QQmlPropertyData data;
+ data.propType = QMetaType::QVariant;
+ data.coreIndex = coreIndex;
+
+ typedef QQmlPropertyCacheMethodArguments A;
+ A *args = static_cast<A *>(malloc(sizeof(A) + (argumentCount + 1) * sizeof(int)));
+ args->arguments[0] = argumentCount;
+ for (int ii = 0; ii < argumentCount; ++ii)
+ args->arguments[ii + 1] = QMetaType::QVariant;
+ args->names = 0;
+ if (argumentCount)
+ args->names = new QList<QByteArray>(names);
+ args->next = argumentsCache;
+ argumentsCache = args;
+ data.arguments = args;
+
+ data.flags = flags;
+
+ QHashedString string(name);
+ if (QQmlPropertyData **old = stringCache.value(string)) {
+ data.overrideIndexIsProperty = !(*old)->isFunction();
+ data.overrideIndex = (*old)->coreIndex;
+ }
+
+ methodIndexCache.append(data);
+
+ stringCache.insert(string, methodIndexCache.data() + methodIndexCache.count() - 1);
+}
+
+void QQmlPropertyCache::appendMethod(const QHashedCStringRef &name, quint32 flags, int coreIndex,
+ const QList<QByteArray> &names)
+{
+ int argumentCount = names.count();
+
+ QQmlPropertyData data;
+ data.propType = QMetaType::QVariant;
+ data.coreIndex = coreIndex;
+
+ typedef QQmlPropertyCacheMethodArguments A;
+ A *args = static_cast<A *>(malloc(sizeof(A) + (argumentCount + 1) * sizeof(int)));
+ args->arguments[0] = argumentCount;
+ for (int ii = 0; ii < argumentCount; ++ii)
+ args->arguments[ii + 1] = QMetaType::QVariant;
+ args->names = 0;
+ if (argumentCount)
+ args->names = new QList<QByteArray>(names);
+ args->next = argumentsCache;
+ argumentsCache = args;
+ data.arguments = args;
+
+ data.flags = flags;
+
+ if (QQmlPropertyData **old = stringCache.value(name)) {
+ data.overrideIndexIsProperty = !(*old)->isFunction();
+ data.overrideIndex = (*old)->coreIndex;
+ }
+
+ methodIndexCache.append(data);
+
+ stringCache.insert(name, methodIndexCache.data() + methodIndexCache.count() - 1);
+}
+
+// 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()
+{
+ if (!_metaObject) {
+ _ownMetaObject = true;
+
+ QMetaObjectBuilder builder;
+ toMetaObjectBuilder(builder);
+ builder.setSuperClass(_parent->createMetaObject());
+ _metaObject = builder.toMetaObject();
+ }
+
+ 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());
+}
+
+QQmlPropertyCache *QQmlPropertyCache::parent() const
+{
+ return _parent;
+}
+
+// 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(QQmlEngine *engine, const QMetaObject *metaObject,
QQmlPropertyData::Flag propertyFlags,
@@ -333,14 +588,6 @@ QQmlPropertyCache::copyAndAppend(QQmlEngine *engine, const QMetaObject *metaObje
}
void QQmlPropertyCache::append(QQmlEngine *engine, const QMetaObject *metaObject,
- QQmlPropertyData::Flag propertyFlags,
- QQmlPropertyData::Flag methodFlags,
- QQmlPropertyData::Flag signalFlags)
-{
- append(engine, metaObject, -1, propertyFlags, methodFlags, signalFlags);
-}
-
-void QQmlPropertyCache::append(QQmlEngine *engine, const QMetaObject *metaObject,
int revision,
QQmlPropertyData::Flag propertyFlags,
QQmlPropertyData::Flag methodFlags,
@@ -349,7 +596,7 @@ void QQmlPropertyCache::append(QQmlEngine *engine, const QMetaObject *metaObject
Q_UNUSED(revision);
Q_ASSERT(constructor.IsEmpty()); // We should not be appending to an in-use property cache
- this->metaObject = metaObject;
+ _metaObject = metaObject;
bool dynamicMetaObject = isDynamicMetaObject(metaObject);
@@ -370,7 +617,8 @@ void QQmlPropertyCache::append(QQmlEngine *engine, const QMetaObject *metaObject
if (0 == qstrcmp(metaObject->classInfo(idx).name(), "qt_HasQmlAccessors")) {
hasFastProperty = true;
- break;
+ } else if (0 == qstrcmp(metaObject->classInfo(idx).name(), "DefaultProperty")) {
+ _defaultPropertyName = QString::fromUtf8(metaObject->classInfo(idx).value());
}
}
@@ -400,7 +648,7 @@ void QQmlPropertyCache::append(QQmlEngine *engine, const QMetaObject *metaObject
// update() should have reserved enough space in the vector that this doesn't cause a realloc
// and invalidate the stringCache.
methodIndexCache.resize(methodCount - methodIndexCacheStart);
- signalHandlerIndexCache.resize(signalCount - signalHanderIndexCacheStart);
+ signalHandlerIndexCache.resize(signalCount - signalHandlerIndexCacheStart);
int signalHandlerIndex = signalOffset;
for (int ii = methodOffset; ii < methodCount; ++ii) {
if (ii == destroyedIdx1 || ii == destroyedIdx2 || ii == deleteLaterIdx)
@@ -443,7 +691,7 @@ void QQmlPropertyCache::append(QQmlEngine *engine, const QMetaObject *metaObject
data->metaObjectOffset = allowedRevisionCache.count() - 1;
if (data->isSignal()) {
- sigdata = &signalHandlerIndexCache[signalHandlerIndex - signalHanderIndexCacheStart];
+ sigdata = &signalHandlerIndexCache[signalHandlerIndex - signalHandlerIndexCacheStart];
*sigdata = *data;
sigdata->flags |= QQmlPropertyData::IsSignalHandler;
}
@@ -572,7 +820,7 @@ void QQmlPropertyCache::updateRecur(QQmlEngine *engine, const QMetaObject *metaO
updateRecur(engine, metaObject->superClass());
- append(engine, metaObject);
+ append(engine, metaObject, -1);
}
void QQmlPropertyCache::update(QQmlEngine *engine, const QMetaObject *metaObject)
@@ -589,7 +837,7 @@ void QQmlPropertyCache::update(QQmlEngine *engine, const QMetaObject *metaObject
int sc = metaObjectSignalCount(metaObject);
propertyIndexCache.reserve(pc - propertyIndexCacheStart);
methodIndexCache.reserve(mc - methodIndexCacheStart);
- signalHandlerIndexCache.reserve(sc - signalHanderIndexCacheStart);
+ signalHandlerIndexCache.reserve(sc - signalHandlerIndexCacheStart);
// Reserve enough space in the stringCache for all properties/methods/signals including those
// cached in a parent cache.
@@ -605,7 +853,7 @@ QQmlPropertyCache::property(int index) const
return 0;
if (index < propertyIndexCacheStart)
- return parent->property(index);
+ return _parent->property(index);
QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&propertyIndexCache.at(index - propertyIndexCacheStart));
if (rv->notFullyResolved()) resolve(rv);
@@ -619,7 +867,7 @@ QQmlPropertyCache::method(int index) const
return 0;
if (index < methodIndexCacheStart)
- return parent->method(index);
+ return _parent->method(index);
QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&methodIndexCache.at(index - methodIndexCacheStart));
if (rv->notFullyResolved()) resolve(rv);
@@ -711,6 +959,18 @@ static int EnumType(const QMetaObject *metaobj, const QByteArray &str, int type)
return type;
}
+QList<QByteArray> QQmlPropertyCache::methodParameterNames(QObject *object, int index)
+{
+ QQmlData *data = QQmlData::get(object, false);
+ if (data->propertyCache) {
+ QQmlPropertyData *p = data->propertyCache->method(index);
+ if (!p->hasArguments())
+ return QList<QByteArray>();
+ }
+
+ return object->metaObject()->method(index).parameterNames();
+}
+
// Returns an array of the arguments for method \a index. The first entry in the array
// is the number of arguments.
int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index,
@@ -728,19 +988,21 @@ int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index,
Q_ASSERT(index < c->methodIndexCacheStart + c->methodIndexCache.count());
while (index < c->methodIndexCacheStart)
- c = c->parent;
+ c = c->_parent;
QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&c->methodIndexCache.at(index - c->methodIndexCacheStart));
if (rv->arguments)
return static_cast<A *>(rv->arguments)->arguments;
- const QMetaObject *metaObject = object->metaObject();
+ const QMetaObject *metaObject = c->createMetaObject();
+ Q_ASSERT(metaObject);
QMetaMethod m = metaObject->method(index);
int argc = m.parameterCount();
A *args = static_cast<A *>(malloc(sizeof(A) + (argc + 1) * sizeof(int)));
args->arguments[0] = argc;
+ args->names = 0;
QList<QByteArray> argTypeNames; // Only loaded if needed
for (int ii = 0; ii < argc; ++ii) {
@@ -800,8 +1062,7 @@ int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index,
}
}
-QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject,
- const QString &property)
+QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject, const QString &property)
{
Q_ASSERT(metaObject);
@@ -861,24 +1122,21 @@ inline QString qQmlPropertyCacheToString(const QHashedV8String &string)
template<typename T>
QQmlPropertyData *
-qQmlPropertyCacheProperty(QQmlEngine *engine, QObject *obj,
- const T &name, QQmlPropertyData &local)
+qQmlPropertyCacheProperty(QQmlEngine *engine, QObject *obj, const T &name, QQmlPropertyData &local)
{
QQmlPropertyCache *cache = 0;
- if (engine) {
- QQmlData *ddata = QQmlData::get(obj);
-
- if (ddata && ddata->propertyCache) {
- cache = ddata->propertyCache;
- } else if (engine) {
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
- cache = ep->cache(obj);
- if (cache) {
- ddata = QQmlData::get(obj, true);
- cache->addref();
- ddata->propertyCache = cache;
- }
+ QQmlData *ddata = QQmlData::get(obj, false);
+
+ if (ddata && ddata->propertyCache) {
+ cache = ddata->propertyCache;
+ } else if (engine) {
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
+ cache = ep->cache(obj);
+ if (cache) {
+ ddata = QQmlData::get(obj, true);
+ cache->addref();
+ ddata->propertyCache = cache;
}
}
@@ -887,8 +1145,7 @@ qQmlPropertyCacheProperty(QQmlEngine *engine, QObject *obj,
if (cache) {
rv = cache->property(name);
} else {
- local = qQmlPropertyCacheCreate(obj->metaObject(),
- qQmlPropertyCacheToString(name));
+ local = qQmlPropertyCacheCreate(obj->metaObject(), qQmlPropertyCacheToString(name));
if (local.isValid())
rv = &local;
}
@@ -918,4 +1175,183 @@ bool QQmlPropertyCache::isDynamicMetaObject(const QMetaObject *mo)
return priv(mo->d.data)->revision >= 3 && priv(mo->d.data)->flags & DynamicMetaObject;
}
+const char *QQmlPropertyCache::className() const
+{
+ if (!_ownMetaObject && _metaObject)
+ return _metaObject->className();
+ else
+ return _dynamicClassName.constData();
+}
+
+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;
+ } };
+
+ struct Insert { static void in(QQmlPropertyCache *This,
+ QList<QPair<QString, QQmlPropertyData *> > &properties,
+ QList<QPair<QString, QQmlPropertyData *> > &methods,
+ StringCache::ConstIterator iter, QQmlPropertyData *data) {
+ if (data->isSignalHandler())
+ return;
+
+ if (data->isFunction()) {
+ if (data->coreIndex < This->methodIndexCacheStart)
+ return;
+
+ QPair<QString, QQmlPropertyData *> entry = qMakePair((QString)iter.key(), data);
+ // Overrides can cause the entry to already exist
+ if (!methods.contains(entry)) methods.append(entry);
+
+ QQmlPropertyData *olddata = data;
+ data = This->overrideData(data);
+ if (data) Insert::in(This, properties, methods, iter, data);
+ } else {
+ if (data->coreIndex < This->propertyIndexCacheStart)
+ return;
+
+ QPair<QString, QQmlPropertyData *> entry = qMakePair((QString)iter.key(), data);
+ // Overrides can cause the entry to already exist
+ if (!properties.contains(entry)) properties.append(entry);
+
+ QQmlPropertyData *olddata = data;
+ data = This->overrideData(data);
+ if (data) Insert::in(This, properties, methods, iter, data);
+ }
+
+ } };
+
+ builder.setClassName(_dynamicClassName);
+
+ QList<QPair<QString, QQmlPropertyData *> > properties;
+ QList<QPair<QString, QQmlPropertyData *> > methods;
+
+ for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter)
+ Insert::in(this, properties, methods, iter, iter.value());
+
+ Q_ASSERT(properties.count() == propertyIndexCache.count());
+ Q_ASSERT(methods.count() == methodIndexCache.count());
+
+ qSort(properties.begin(), properties.end(), Sort::lt);
+ qSort(methods.begin(), methods.end(), Sort::lt);
+
+ for (int ii = 0; ii < properties.count(); ++ii) {
+ QQmlPropertyData *data = properties.at(ii).second;
+
+ int notifierId = -1;
+ if (data->notifyIndex != -1)
+ notifierId = data->notifyIndex - methodIndexCacheStart;
+
+ QMetaPropertyBuilder property = builder.addProperty(properties.at(ii).first.toUtf8(),
+ QMetaType::typeName(data->propType),
+ notifierId);
+
+ property.setReadable(true);
+ property.setWritable(data->isWritable());
+ property.setResettable(data->isResettable());
+ }
+
+ for (int ii = 0; ii < methods.count(); ++ii) {
+ QQmlPropertyData *data = methods.at(ii).second;
+
+ QByteArray returnType;
+ if (data->propType != 0)
+ returnType = QMetaType::typeName(data->propType);
+
+ QByteArray signature = methods.at(ii).first.toUtf8() + "(";
+
+ QQmlPropertyCacheMethodArguments *arguments = 0;
+ if (data->hasArguments()) {
+ arguments = (QQmlPropertyCacheMethodArguments *)data->arguments;
+
+ for (int ii = 0; ii < arguments->arguments[0]; ++ii) {
+ if (ii != 0) signature.append(",");
+ signature.append(QMetaType::typeName(arguments->arguments[1 + ii]));
+ }
+ }
+
+ signature.append(")");
+
+ QMetaMethodBuilder method;
+ if (data->isSignal()) {
+ method = builder.addSignal(signature);
+ } else {
+ method = builder.addSlot(signature);
+ }
+ method.setAccess(QMetaMethod::Protected);
+
+ if (arguments && arguments->names)
+ method.setParameterNames(*arguments->names);
+
+ if (!returnType.isEmpty())
+ method.setReturnType(returnType);
+ }
+
+ if (!_defaultPropertyName.isEmpty()) {
+ QQmlPropertyData *dp = property(_defaultPropertyName);
+ if (dp && dp->coreIndex >= propertyIndexCacheStart) {
+ Q_ASSERT(!dp->isFunction());
+ builder.addClassInfo("DefaultProperty", _defaultPropertyName.toUtf8());
+ }
+ }
+}
+
+// Returns true if \a from is assignable to a property of type \a to
+bool QQmlMetaObject::canConvert(const QQmlMetaObject &from, const QQmlMetaObject &to)
+{
+ Q_ASSERT(!from.isNull() && !to.isNull());
+
+ struct I { static bool equal(const QMetaObject *lhs, const QMetaObject *rhs) {
+ return lhs == rhs || (lhs && rhs && lhs->d.stringdata == rhs->d.stringdata);
+ } };
+
+ const QMetaObject *tom = to._m.isT1()?to._m.asT1()->metaObject():to._m.asT2();
+ if (tom == &QObject::staticMetaObject) return true;
+
+ if (from._m.isT1() && to._m.isT1()) { // QQmlPropertyCache -> QQmlPropertyCache
+ QQmlPropertyCache *fromp = from._m.asT1();
+ QQmlPropertyCache *top = to._m.asT1();
+
+ while (fromp) {
+ if (fromp == top) return true;
+ fromp = fromp->parent();
+ }
+ } else if (from._m.isT1() && to._m.isT2()) { // QQmlPropertyCache -> QMetaObject
+ QQmlPropertyCache *fromp = from._m.asT1();
+
+ while (fromp) {
+ const QMetaObject *fromm = fromp->metaObject();
+ if (fromm && I::equal(fromm, tom)) return true;
+ fromp = fromp->parent();
+ }
+ } else if (from._m.isT2() && to._m.isT1()) { // QMetaObject -> QQmlPropertyCache
+ const QMetaObject *fromm = from._m.asT2();
+
+ if (!tom) return false;
+
+ while (fromm) {
+ if (I::equal(fromm, tom)) return true;
+ fromm = fromm->superClass();
+ }
+ } else { // QMetaObject -> QMetaObject
+ const QMetaObject *fromm = from._m.asT2();
+
+ while (fromm) {
+ if (I::equal(fromm, tom)) return true;
+ fromm = fromm->superClass();
+ }
+ }
+
+ return false;
+}
+
+QQmlPropertyCache *QQmlMetaObject::propertyCache(QQmlEnginePrivate *e) const
+{
+ if (_m.isNull()) return 0;
+ if (_m.isT1()) return _m.asT1();
+ else return e->cache(_m.asT2());
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 98322b0275..3be85c7003 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -54,6 +54,7 @@
//
#include <private/qqmlrefcount_p.h>
+#include <private/qflagpointer_p.h>
#include "qqmlcleanup_p.h"
#include "qqmlnotifier_p.h"
@@ -69,6 +70,7 @@ class QV8QObjectWrapper;
class QQmlEngine;
class QQmlPropertyData;
class QQmlAccessors;
+class QMetaObjectBuilder;
class QQmlPropertyCacheMethodArguments;
// We have this somewhat awful split between RawData and Data so that RawData can be
@@ -98,7 +100,7 @@ public:
IsQmlBinding = 0x00000800, // Property type is a QQmlBinding*
IsQJSValue = 0x00001000, // Property type is a QScriptValue
IsV8Handle = 0x00002000, // Property type is a QQmlV8Handle
- IsVMEProperty = 0x00004000, // Property type is a "var" property of VMEMO
+ IsVarProperty = 0x00004000, // Property type is a "var" property of VMEMO
IsValueTypeVirtual = 0x00008000, // Property is a value type "virtual" property
IsQVariant = 0x00010000, // Property is a QVariant
@@ -110,9 +112,14 @@ public:
IsV8Function = 0x00200000, // Function takes QQmlV8Function* args
IsSignalHandler = 0x00400000, // Function is a signal handler
IsOverload = 0x00800000, // Function is an overload of another function
+ IsCloned = 0x01000000, // The function was marked as cloned
// Internal QQmlPropertyCache flags
- NotFullyResolved = 0x01000000 // True if the type data is to be lazily resolved
+ NotFullyResolved = 0x02000000, // True if the type data is to be lazily resolved
+
+ // Flags that are set based on the propType field
+ PropTypeFlagMask = IsQObjectDerived | IsEnumType | IsQList | IsQmlBinding | IsQJSValue |
+ IsV8Handle | IsQVariant,
};
Q_DECLARE_FLAGS(Flags, Flag)
@@ -135,7 +142,7 @@ public:
bool isQmlBinding() const { return flags & IsQmlBinding; }
bool isQJSValue() const { return flags & IsQJSValue; }
bool isV8Handle() const { return flags & IsV8Handle; }
- bool isVMEProperty() const { return flags & IsVMEProperty; }
+ bool isVarProperty() const { return flags & IsVarProperty; }
bool isValueTypeVirtual() const { return flags & IsValueTypeVirtual; }
bool isQVariant() const { return flags & IsQVariant; }
bool isVMEFunction() const { return flags & IsVMEFunction; }
@@ -145,6 +152,7 @@ public:
bool isV8Function() const { return flags & IsV8Function; }
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) &&
@@ -243,14 +251,24 @@ public:
QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
- void append(QQmlEngine *, const QMetaObject *,
- QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
- QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
- QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
- void append(QQmlEngine *, const QMetaObject *, int revision,
- QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
- QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
- QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
+ QQmlPropertyCache *copyAndReserve(QQmlEngine *, int propertyCount,
+ int methodCount, int signalCount);
+ void appendProperty(const QString &,
+ quint32 flags, int coreIndex, int propType, int notifyIndex);
+ void appendProperty(const QHashedCStringRef &,
+ 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 appendSignal(const QHashedCStringRef &, quint32, int coreIndex, const int *types = 0,
+ const QList<QByteArray> &names = QList<QByteArray>());
+ void appendMethod(const QString &, quint32 flags, int coreIndex,
+ const QList<QByteArray> &names = QList<QByteArray>());
+ void appendMethod(const QHashedCStringRef &, quint32 flags, int coreIndex,
+ const QList<QByteArray> &names = QList<QByteArray>());
+
+ const QMetaObject *metaObject() const;
+ const QMetaObject *createMetaObject();
+ const QMetaObject *firstCppMetaObject() const;
inline QQmlPropertyData *property(const QHashedV8String &) const;
QQmlPropertyData *property(const QHashedStringRef &) const;
@@ -260,6 +278,10 @@ public:
QQmlPropertyData *method(int) const;
QStringList propertyNames() const;
+ QString defaultPropertyName() const;
+ QQmlPropertyData *defaultProperty() const;
+ QQmlPropertyCache *parent() const;
+
inline QQmlPropertyData *overrideData(QQmlPropertyData *) const;
inline bool isAllowedInRevision(QQmlPropertyData *) const;
@@ -270,8 +292,21 @@ public:
QQmlPropertyData &);
static int *methodParameterTypes(QObject *, int index, QVarLengthArray<int, 9> &dummy,
QByteArray *unknownTypeError);
+ static QList<QByteArray> methodParameterNames(QObject *, int index);
+
+ const char *className() const;
+
+ inline int propertyCount() const;
+ inline int propertyOffset() const;
+ inline int methodCount() const;
+ inline int methodOffset() const;
+ inline int signalCount() const;
+ inline int signalOffset() const;
static bool isDynamicMetaObject(const QMetaObject *);
+
+ void toMetaObjectBuilder(QMetaObjectBuilder &);
+
protected:
virtual void destroy();
virtual void clear();
@@ -279,9 +314,15 @@ protected:
private:
friend class QQmlEnginePrivate;
friend class QV8QObjectWrapper;
+ friend class QQmlCompiler;
inline QQmlPropertyCache *copy(int reserve);
+ void append(QQmlEngine *, const QMetaObject *, int revision,
+ QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
+ QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
+ QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
+
// Implemented in v8/qv8qobjectwrapper.cpp
v8::Local<v8::Object> newQObject(QObject *, QV8Engine *);
@@ -293,11 +334,11 @@ private:
void updateRecur(QQmlEngine *, const QMetaObject *);
QQmlEngine *engine;
-
- QQmlPropertyCache *parent;
+
+ QQmlPropertyCache *_parent;
int propertyIndexCacheStart;
int methodIndexCacheStart;
- int signalHanderIndexCacheStart;
+ int signalHandlerIndexCacheStart;
IndexCache propertyIndexCache;
IndexCache methodIndexCache;
@@ -306,9 +347,47 @@ private:
AllowedRevisionCache allowedRevisionCache;
v8::Persistent<v8::Function> constructor;
- const QMetaObject *metaObject;
+ bool _ownMetaObject;
+ const QMetaObject *_metaObject;
+ QByteArray _dynamicClassName;
+ QByteArray _dynamicStringData;
+ QString _defaultPropertyName;
QQmlPropertyCacheMethodArguments *argumentsCache;
};
+
+// QQmlMetaObject serves as a wrapper around either QMetaObject or QQmlPropertyCache.
+// This is necessary as we delay creation of QMetaObject for synthesized QObjects, but
+// we don't want to needlessly generate QQmlPropertyCaches every time we encounter a
+// QObject type used in assignment or when we don't have a QQmlEngine etc.
+//
+// This class does NOT reference the propertycache.
+class QQmlEnginePrivate;
+class Q_QML_EXPORT QQmlMetaObject
+{
+public:
+ inline QQmlMetaObject();
+ inline QQmlMetaObject(QObject *);
+ inline QQmlMetaObject(const QMetaObject *);
+ inline QQmlMetaObject(QQmlPropertyCache *);
+ inline QQmlMetaObject(const QQmlMetaObject &);
+
+ inline QQmlMetaObject &operator=(const QQmlMetaObject &);
+
+ inline bool isNull() const;
+
+ inline const char *className() const;
+ inline int propertyCount() const;
+
+ inline bool hasMetaObject() const;
+ inline const QMetaObject *metaObject() const;
+
+ QQmlPropertyCache *propertyCache(QQmlEnginePrivate *) const;
+
+ static bool canConvert(const QQmlMetaObject &from, const QQmlMetaObject &to);
+
+private:
+ QBiPointer<QQmlPropertyCache, const QMetaObject> _m;
+};
QQmlPropertyData::QQmlPropertyData()
{
@@ -379,6 +458,109 @@ QQmlPropertyData *QQmlPropertyCache::property(const QHashedV8String &str) const
return rv?*rv:0;
}
+int QQmlPropertyCache::propertyCount() const
+{
+ return propertyIndexCacheStart + propertyIndexCache.count();
+}
+
+int QQmlPropertyCache::propertyOffset() const
+{
+ return propertyIndexCacheStart;
+}
+
+int QQmlPropertyCache::methodCount() const
+{
+ return methodIndexCacheStart + methodIndexCache.count();
+}
+
+int QQmlPropertyCache::methodOffset() const
+{
+ return methodIndexCacheStart;
+}
+
+int QQmlPropertyCache::signalCount() const
+{
+ return signalHandlerIndexCacheStart + signalHandlerIndexCache.count();
+}
+
+int QQmlPropertyCache::signalOffset() const
+{
+ return signalHandlerIndexCacheStart;
+}
+
+QQmlMetaObject::QQmlMetaObject()
+{
+}
+
+QQmlMetaObject::QQmlMetaObject(QObject *o)
+{
+ if (o) {
+ QQmlData *ddata = QQmlData::get(o, false);
+ if (ddata && ddata->propertyCache) _m = ddata->propertyCache;
+ else _m = o->metaObject();
+ }
+}
+
+QQmlMetaObject::QQmlMetaObject(const QMetaObject *m)
+: _m(m)
+{
+}
+
+QQmlMetaObject::QQmlMetaObject(QQmlPropertyCache *m)
+: _m(m)
+{
+}
+
+QQmlMetaObject::QQmlMetaObject(const QQmlMetaObject &o)
+: _m(o._m)
+{
+}
+
+QQmlMetaObject &QQmlMetaObject::operator=(const QQmlMetaObject &o)
+{
+ _m = o._m;
+ return *this;
+}
+
+bool QQmlMetaObject::isNull() const
+{
+ return _m.isNull();
+}
+
+const char *QQmlMetaObject::className() const
+{
+ if (_m.isNull()) {
+ return 0;
+ } else if (_m.isT1()) {
+ return _m.asT1()->className();
+ } else {
+ return _m.asT2()->className();
+ }
+}
+
+int QQmlMetaObject::propertyCount() const
+{
+ if (_m.isNull()) {
+ return 0;
+ } else if (_m.isT1()) {
+ return _m.asT1()->propertyCount();
+ } else {
+ return _m.asT2()->propertyCount();
+ }
+}
+
+bool QQmlMetaObject::hasMetaObject() const
+{
+ return _m.isT2() || (!_m.isNull() && _m.asT1()->metaObject());
+}
+
+const QMetaObject *QQmlMetaObject::metaObject() const
+{
+ if (_m.isNull()) return 0;
+ if (_m.isT1()) return _m.asT1()->createMetaObject();
+ else return _m.asT2();
+}
+
QT_END_NAMESPACE
#endif // QQMLPROPERTYCACHE_P_H
diff --git a/src/qml/qml/qqmlscript.cpp b/src/qml/qml/qqmlscript.cpp
index 555eb44e0b..cd32c0d8f8 100644
--- a/src/qml/qml/qqmlscript.cpp
+++ b/src/qml/qml/qqmlscript.cpp
@@ -63,16 +63,10 @@ using namespace QQmlScript;
// Parser IR classes
//
QQmlScript::Object::Object()
-: type(-1), typeReference(0), idIndex(-1), metatype(0), synthCache(0), defaultProperty(0),
- parserStatusCast(-1), componentCompileState(0), nextAliasingObject(0), nextIdObject(0)
+: type(-1), typeReference(0), idIndex(-1), metatype(0), synthCache(0),
+ defaultProperty(0), parserStatusCast(-1), componentCompileState(0), nextAliasingObject(0),
+ nextIdObject(0)
{
- // initialize the members in the meta object
- extObject.d.superdata = 0;
- extObject.d.stringdata = 0;
- extObject.d.data = 0;
- extObject.d.extradata = 0;
- extObject.d.static_metacall = 0;
- extObject.d.relatedMetaObjects = 0;
}
QQmlScript::Object::~Object()
@@ -89,14 +83,6 @@ void Object::setBindingBit(int b)
bits[b / 32] |= (1 << (b % 32));
}
-const QMetaObject *Object::metaObject() const
-{
- if (!metadata.isEmpty() && metatype)
- return &extObject;
- else
- return metatype;
-}
-
QQmlScript::Property *Object::getDefaultProperty()
{
if (!defaultProperty) {
@@ -206,17 +192,18 @@ int QQmlScript::Object::aggregateDynamicSlotParameterCount() const
}
QQmlScript::Object::DynamicProperty::DynamicProperty()
-: isDefaultProperty(false), isReadOnly(false), type(Variant), defaultValue(0), nextProperty(0)
+: isDefaultProperty(false), isReadOnly(false), type(Variant), defaultValue(0), nextProperty(0),
+ nameIndex(-1)
{
}
QQmlScript::Object::DynamicSignal::DynamicSignal()
-: nextSignal(0)
+: nextSignal(0), nameIndex(-1)
{
}
QQmlScript::Object::DynamicSlot::DynamicSlot()
-: nextSlot(0)
+: nextSlot(0), nameIndex(-1)
{
}
diff --git a/src/qml/qml/qqmlscript_p.h b/src/qml/qml/qqmlscript_p.h
index daf9fdce14..486c573754 100644
--- a/src/qml/qml/qqmlscript_p.h
+++ b/src/qml/qml/qqmlscript_p.h
@@ -56,7 +56,6 @@
#include <private/qfieldlist_p.h>
#include <private/qhashfield_p.h>
-#include <private/qfastmetabuilder_p.h>
#include <private/qqmlpool_p.h>
#include <private/qqmlpropertycache_p.h>
@@ -320,17 +319,12 @@ public:
// Bit mask of the properties assigned bindings
QByteArray bindingBitmask;
void setBindingBit(int);
- // Returns the metaobject for this type, or 0 if not available.
- // Internally selectd between the metatype and extObject variables
- const QMetaObject *metaObject() const;
- // The compile time metaobject for this type
- const QMetaObject *metatype;
+ QQmlPropertyCache *metatype;
+
// The synthesized metaobject, if QML added signals or properties to
// this type. Otherwise null
- QAbstractDynamicMetaObject extObject;
- QByteArray metadata; // Generated by compiler
- QByteArray synthdata; // Generated by compiler
+ QByteArray synthdata; // Generated by compiler
QQmlPropertyCache *synthCache; // Generated by compiler
Property *getDefaultProperty();
@@ -404,8 +398,7 @@ public:
DynamicProperty *nextProperty;
// Used by the compiler
- QFastMetaBuilder::StringRef nameRef;
- QFastMetaBuilder::StringRef changedNameRef;
+ int nameIndex; // Points at the name and name + "Changed()" strings
};
struct DynamicSignal : public QQmlPool::POD
@@ -420,8 +413,7 @@ public:
DynamicSignal *nextSignal;
// Used by the compiler
- QFastMetaBuilder::StringRef nameRef;
- QQmlPool::List<QFastMetaBuilder::StringRef> parameterNamesRef;
+ int nameIndex;
LocationSpan location;
};
@@ -440,8 +432,7 @@ public:
DynamicSlot *nextSlot;
// Used by the compiler
- QFastMetaBuilder::StringRef nameRef;
- QQmlPool::List<QFastMetaBuilder::StringRef> parameterNamesRef;
+ int nameIndex;
};
// The list of dynamic properties
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index f76ded631c..97b8634f39 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -1215,7 +1215,7 @@ loaded files.
*/
QQmlTypeLoader::~QQmlTypeLoader()
{
- clearCache(0, 0);
+ clearCache();
}
/*!
@@ -1563,12 +1563,9 @@ const QQmlDirParser *QQmlTypeLoader::qmlDirParser(const QString &filePath,
Clears cached information about loaded files, including any type data, scripts
and qmldir information.
*/
-void QQmlTypeLoader::clearCache(void (*callback)(void *, QQmlTypeData *), void *arg)
+void QQmlTypeLoader::clearCache()
{
for (TypeCache::Iterator iter = m_typeCache.begin(); iter != m_typeCache.end(); ++iter) {
- if (callback)
- (*callback)(arg, iter.value());
-
(*iter)->release();
}
for (ScriptCache::Iterator iter = m_scriptCache.begin(); iter != m_scriptCache.end(); ++iter)
@@ -1585,7 +1582,7 @@ void QQmlTypeLoader::clearCache(void (*callback)(void *, QQmlTypeData *), void *
m_importQmlDirCache.clear();
}
-void QQmlTypeLoader::trimCache(void (*callback)(void *, QQmlTypeData *), void *arg)
+void QQmlTypeLoader::trimCache()
{
while (true) {
QList<TypeCache::Iterator> unneededTypes;
@@ -1604,11 +1601,8 @@ void QQmlTypeLoader::trimCache(void (*callback)(void *, QQmlTypeData *), void *a
TypeCache::Iterator iter = unneededTypes.last();
unneededTypes.removeLast();
- QQmlTypeData *typeData = iter.value();
- if (callback)
- (*callback)(arg, typeData);
+ iter.value()->release();
m_typeCache.erase(iter);
- typeData->release();
}
}
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index a795d3c816..b16421a8ee 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -279,17 +279,8 @@ public:
bool directoryExists(const QString &path);
const QQmlDirParser *qmlDirParser(const QString &filePath, const QString &uriHint, QString *outUrl);
- template<typename T>
- void clearCache(T *o, void (T::*callback)(QQmlTypeData *)) {
- TypedCallback<T> cb(o, callback);
- clearCache(&TypedCallback<T>::redirect, &cb);
- }
-
- template<typename T>
- void trimCache(T *o, void (T::*callback)(QQmlTypeData *)) {
- TypedCallback<T> cb(o, callback);
- trimCache(&TypedCallback<T>::redirect, &cb);
- }
+ void clearCache();
+ void trimCache();
bool isTypeLoaded(const QUrl &url) const;
bool isScriptLoaded(const QUrl &url) const;
@@ -314,9 +305,6 @@ private:
void (T::*mf)(QQmlTypeData *);
};
- void clearCache(void (*callback)(void *, QQmlTypeData *), void *);
- void trimCache(void (*callback)(void *, QQmlTypeData *), void *);
-
struct DirParser : public QQmlDirParser { QString adjustedUrl; };
typedef QHash<QUrl, QQmlTypeData *> TypeCache;
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index 1665342ffd..c09971bede 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -45,7 +45,6 @@
#include "qqmlboundsignal_p.h"
#include "qqmlstringconverters_p.h"
#include <private/qmetaobjectbuilder_p.h>
-#include <private/qfastmetabuilder_p.h>
#include "qqmldata_p.h"
#include "qqml.h"
#include "qqmlcustomparser_p.h"
@@ -691,21 +690,18 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_BEGIN_INSTR(StoreMetaObject)
QObject *target = objects.top();
- QMetaObject mo;
- const QByteArray &metadata = DATAS.at(instr.data);
- QFastMetaBuilder::fromData(&mo, 0, metadata);
+ QQmlPropertyCache *propertyCache = PROPERTYCACHES.at(instr.propertyCache);
const QQmlVMEMetaData *data =
(const QQmlVMEMetaData *)DATAS.at(instr.aliasData).constData();
- (void)new QQmlVMEMetaObject(target, &mo, data);
+ (void)new QQmlVMEMetaObject(target, propertyCache, data);
+
+ QQmlData *ddata = QQmlData::get(target, true);
+ if (ddata->propertyCache) ddata->propertyCache->release();
+ ddata->propertyCache = propertyCache;
+ ddata->propertyCache->addref();
- if (instr.propertyCache != -1) {
- QQmlData *ddata = QQmlData::get(target, true);
- if (ddata->propertyCache) ddata->propertyCache->release();
- ddata->propertyCache = PROPERTYCACHES.at(instr.propertyCache);
- ddata->propertyCache->addref();
- }
QML_END_INSTR(StoreMetaObject)
QML_BEGIN_INSTR(AssignCustomType)
@@ -761,9 +757,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QObject *target = objects.top();
QObject *context = objects.at(objects.count() - 1 - instr.context);
- QMetaMethod signal = target->metaObject()->method(instr.signalIndex);
-
- QQmlBoundSignal *bs = new QQmlBoundSignal(target, signal, target, engine);
+ QQmlBoundSignal *bs = new QQmlBoundSignal(target, instr.signalIndex, target, engine);
QQmlBoundSignalExpression *expr =
new QQmlBoundSignalExpression(CTXT, context, DATAS.at(instr.value), true, COMP->name, instr.line, instr.column);
bs->takeExpression(expr);
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 77a0482edf..e0d797269c 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -69,7 +69,7 @@ QQmlVMEVariantQObjectPtr::~QQmlVMEVariantQObjectPtr()
void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *)
{
if (m_target && m_index >= 0)
- m_target->activate(m_target->object, m_target->methodOffset + m_index, 0);
+ m_target->activate(m_target->object, m_target->methodOffset() + m_index, 0);
}
void QQmlVMEVariantQObjectPtr::setGuardedValue(QObject *obj, QQmlVMEMetaObject *target, int index)
@@ -461,8 +461,8 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
if (metaObject.flag()) {
// This is actually notify
- int sigIdx = metaObject->methodOffset + aliasId + metaObject->metaData->propertyCount;
- QMetaObject::activate(metaObject->object, sigIdx, 0);
+ int sigIdx = metaObject->methodOffset() + aliasId + metaObject->metaData->propertyCount;
+ metaObject->activate(metaObject->object, sigIdx, 0);
} else {
QQmlVMEMetaData::AliasData *d = metaObject->metaData->aliasData() + aliasId;
if (!d->isObjectAlias()) {
@@ -471,33 +471,46 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
if (!target)
return;
- QMetaProperty prop = target->metaObject()->property(d->propertyIndex());
- if (prop.hasNotifySignal())
- connect(target, prop.notifySignalIndex(), ctxt->engine);
+ if (d->notifySignal != -1)
+ connect(target, d->notifySignal, ctxt->engine);
}
metaObject.setFlag();
}
}
-QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj, const QMetaObject *other, const QQmlVMEMetaData *meta)
-: QV8GCCallback::Node(GcPrologueCallback), object(obj),
- ctxt(QQmlData::get(obj, true)->outerContext), metaData(meta), data(0),
- aliasEndpoints(0), firstVarPropertyIndex(-1), varPropertiesInitialized(false),
- interceptors(0), v8methods(0), parent(0)
+QAbstractDynamicMetaObject *QQmlVMEMetaObject::toDynamicMetaObject(QObject *o)
{
- *static_cast<QMetaObject *>(this) = *other;
- this->d.superdata = obj->metaObject();
+ if (!hasAssignedMetaObjectData) {
+ *static_cast<QMetaObject *>(this) = *cache->createMetaObject();
+
+ if (parent.isT1())
+ this->d.superdata = parent.asT1()->toDynamicMetaObject(o);
+ else
+ this->d.superdata = parent.asT2();
+
+ hasAssignedMetaObjectData = true;
+ }
+
+ return this;
+}
+QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
+ QQmlPropertyCache *cache,
+ const QQmlVMEMetaData *meta)
+: QV8GCCallback::Node(GcPrologueCallback), object(obj),
+ ctxt(QQmlData::get(obj, true)->outerContext), cache(cache), metaData(meta),
+ hasAssignedMetaObjectData(false), data(0), aliasEndpoints(0), firstVarPropertyIndex(-1),
+ varPropertiesInitialized(false), interceptors(0), v8methods(0)
+{
QObjectPrivate *op = QObjectPrivate::get(obj);
- if (op->metaObject)
- parent = static_cast<QAbstractDynamicMetaObject*>(op->metaObject);
+
+ if (op->metaObject) parent = op->metaObject;
+ else parent = obj->metaObject();
+
op->metaObject = this;
QQmlData::get(obj)->hasVMEMetaObject = true;
- propOffset = QAbstractDynamicMetaObject::propertyOffset();
- methodOffset = QAbstractDynamicMetaObject::methodOffset();
-
data = new QQmlVMEVariant[metaData->propertyCount - metaData->varPropertyCount];
aConnected.resize(metaData->aliasCount);
@@ -507,7 +520,7 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj, const QMetaObject *other, con
for (int ii = 0; ii < metaData->propertyCount - metaData->varPropertyCount; ++ii) {
int t = (metaData->propertyData() + ii)->propertyType;
if (t == list_type) {
- listProperties.append(List(methodOffset + ii));
+ listProperties.append(List(methodOffset() + ii, this));
data[ii].setValue(listProperties.count() - 1);
}
}
@@ -519,7 +532,7 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj, const QMetaObject *other, con
QQmlVMEMetaObject::~QQmlVMEMetaObject()
{
- delete parent;
+ if (parent.isT1()) parent.asT1()->objectDestroyed(object);
delete [] data;
delete [] aliasEndpoints;
@@ -543,7 +556,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
continue;
int valueIndex = vi->m_valueTypeCoreIndex;
- int type = property(id).userType();
+ int type = QQmlData::get(object)->propertyCache->property(id)->propType;
if (type != QVariant::Invalid) {
if (valueIndex != -1) {
@@ -567,8 +580,8 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
}
}
if (c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty || c == QMetaObject::ResetProperty) {
- if (id >= propOffset) {
- id -= propOffset;
+ if (id >= propOffset()) {
+ id -= propOffset();
if (id < metaData->propertyCount) {
int t = (metaData->propertyData() + id)->propertyType;
@@ -692,7 +705,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
}
if (c == QMetaObject::WriteProperty && needActivate) {
- activate(object, methodOffset + id, 0);
+ activate(object, methodOffset() + id, 0);
}
return -1;
@@ -761,13 +774,13 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
} else if(c == QMetaObject::InvokeMetaMethod) {
- if (id >= methodOffset) {
+ if (id >= methodOffset()) {
- id -= methodOffset;
+ id -= methodOffset();
int plainSignals = metaData->signalCount + metaData->propertyCount +
metaData->aliasCount;
if (id < plainSignals) {
- QMetaObject::activate(object, _id, a);
+ activate(object, _id, a);
return -1;
}
@@ -827,8 +840,8 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
}
}
- if (parent)
- return parent->metaCall(c, _id, a);
+ if (parent.isT1())
+ return parent.asT1()->metaCall(object, c, _id, a);
else
return object->qt_metacall(c, _id, a);
}
@@ -912,7 +925,7 @@ void QQmlVMEMetaObject::writeVarProperty(int id, v8::Handle<v8::Value> value)
// Write the value and emit change signal as appropriate.
varProperties->Set(id - firstVarPropertyIndex, value);
- activate(object, methodOffset + id, 0);
+ activate(object, methodOffset() + id, 0);
}
void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
@@ -945,13 +958,13 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
QVariant currentValue = readPropertyAsVariant(id);
varProperties->Set(id - firstVarPropertyIndex, newv);
if ((currentValue.userType() != value.userType() || currentValue != value))
- activate(object, methodOffset + id, 0);
+ activate(object, methodOffset() + id, 0);
} else {
bool needActivate = false;
if (value.userType() == QMetaType::QObjectStar) {
- QObject *o = qvariant_cast<QObject *>(value);
+ QObject *o = *(QObject **)value.data();
needActivate = (data[id].dataType() != QMetaType::QObjectStar || data[id].asQObject() != o);
- data[id].setValue(qvariant_cast<QObject *>(value), this, id);
+ data[id].setValue(o, this, id);
} else {
needActivate = (data[id].dataType() != qMetaTypeId<QVariant>() ||
data[id].asQVariant().userType() != value.userType() ||
@@ -960,20 +973,20 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
}
if (needActivate)
- activate(object, methodOffset + id, 0);
+ activate(object, methodOffset() + id, 0);
}
}
void QQmlVMEMetaObject::listChanged(int id)
{
- activate(object, methodOffset + id, 0);
+ activate(object, methodOffset() + id, 0);
}
void QQmlVMEMetaObject::list_append(QQmlListProperty<QObject> *prop, QObject *o)
{
List *list = static_cast<List *>(prop->data);
list->append(o);
- QMetaObject::activate(prop->object, list->notifyIndex, 0);
+ list->mo->activate(prop->object, list->notifyIndex, 0);
}
int QQmlVMEMetaObject::list_count(QQmlListProperty<QObject> *prop)
@@ -990,7 +1003,7 @@ void QQmlVMEMetaObject::list_clear(QQmlListProperty<QObject> *prop)
{
List *list = static_cast<List *>(prop->data);
list->clear();
- QMetaObject::activate(prop->object, list->notifyIndex, 0);
+ list->mo->activate(prop->object, list->notifyIndex, 0);
}
void QQmlVMEMetaObject::registerInterceptor(int index, int valueIndex, QQmlPropertyValueInterceptor *interceptor)
@@ -1003,15 +1016,15 @@ void QQmlVMEMetaObject::registerInterceptor(int index, int valueIndex, QQmlPrope
int QQmlVMEMetaObject::vmeMethodLineNumber(int index)
{
- if (index < methodOffset) {
- Q_ASSERT(parent);
- return static_cast<QQmlVMEMetaObject *>(parent)->vmeMethodLineNumber(index);
+ if (index < methodOffset()) {
+ Q_ASSERT(parent.isT1());
+ return static_cast<QQmlVMEMetaObject *>(parent.asT1())->vmeMethodLineNumber(index);
}
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
- Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + plainSignals + metaData->methodCount));
+ Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
- int rawIndex = index - methodOffset - plainSignals;
+ int rawIndex = index - methodOffset() - plainSignals;
QQmlVMEMetaData::MethodData *data = metaData->methodData() + rawIndex;
return data->lineNumber;
@@ -1019,29 +1032,29 @@ int QQmlVMEMetaObject::vmeMethodLineNumber(int index)
v8::Handle<v8::Function> QQmlVMEMetaObject::vmeMethod(int index)
{
- if (index < methodOffset) {
- Q_ASSERT(parent);
- return static_cast<QQmlVMEMetaObject *>(parent)->vmeMethod(index);
+ if (index < methodOffset()) {
+ Q_ASSERT(parent.isT1());
+ return static_cast<QQmlVMEMetaObject *>(parent.asT1())->vmeMethod(index);
}
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
- Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + plainSignals + metaData->methodCount));
- return method(index - methodOffset - plainSignals);
+ Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
+ return method(index - methodOffset() - plainSignals);
}
// Used by debugger
void QQmlVMEMetaObject::setVmeMethod(int index, v8::Persistent<v8::Function> value)
{
- if (index < methodOffset) {
- Q_ASSERT(parent);
- return static_cast<QQmlVMEMetaObject *>(parent)->setVmeMethod(index, value);
+ if (index < methodOffset()) {
+ Q_ASSERT(parent.isT1());
+ return static_cast<QQmlVMEMetaObject *>(parent.asT1())->setVmeMethod(index, value);
}
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
- Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + plainSignals + metaData->methodCount));
+ Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
if (!v8methods)
v8methods = new v8::Persistent<v8::Function>[metaData->methodCount];
- int methodIndex = index - methodOffset - plainSignals;
+ int methodIndex = index - methodOffset() - plainSignals;
if (!v8methods[methodIndex].IsEmpty())
qPersistentDispose(v8methods[methodIndex]);
v8methods[methodIndex] = value;
@@ -1049,21 +1062,21 @@ void QQmlVMEMetaObject::setVmeMethod(int index, v8::Persistent<v8::Function> val
v8::Handle<v8::Value> QQmlVMEMetaObject::vmeProperty(int index)
{
- if (index < propOffset) {
- Q_ASSERT(parent);
- return static_cast<QQmlVMEMetaObject *>(parent)->vmeProperty(index);
+ if (index < propOffset()) {
+ Q_ASSERT(parent.isT1());
+ return static_cast<QQmlVMEMetaObject *>(parent.asT1())->vmeProperty(index);
}
- return readVarProperty(index - propOffset);
+ return readVarProperty(index - propOffset());
}
void QQmlVMEMetaObject::setVMEProperty(int index, v8::Handle<v8::Value> v)
{
- if (index < propOffset) {
- Q_ASSERT(parent);
- static_cast<QQmlVMEMetaObject *>(parent)->setVMEProperty(index, v);
+ if (index < propOffset()) {
+ Q_ASSERT(parent.isT1());
+ static_cast<QQmlVMEMetaObject *>(parent.asT1())->setVMEProperty(index, v);
return;
}
- return writeVarProperty(index - propOffset, v);
+ return writeVarProperty(index - propOffset(), v);
}
bool QQmlVMEMetaObject::ensureVarPropertiesAllocated()
@@ -1116,7 +1129,7 @@ void QQmlVMEMetaObject::GcPrologueCallback(QV8GCCallback::Node *node)
bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const
{
- Q_ASSERT(index >= propOffset + metaData->propertyCount);
+ Q_ASSERT(index >= propOffset() + metaData->propertyCount);
*target = 0;
*coreIndex = -1;
@@ -1125,7 +1138,7 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex,
if (!ctxt)
return false;
- QQmlVMEMetaData::AliasData *d = metaData->aliasData() + (index - propOffset - metaData->propertyCount);
+ QQmlVMEMetaData::AliasData *d = metaData->aliasData() + (index - propOffset() - metaData->propertyCount);
QQmlContext *context = ctxt->asQQmlContext();
QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(context);
@@ -1166,11 +1179,39 @@ void QQmlVMEMetaObject::connectAlias(int aliasId)
void QQmlVMEMetaObject::connectAliasSignal(int index)
{
- int aliasId = (index - methodOffset) - metaData->propertyCount;
+ int aliasId = (index - methodOffset()) - metaData->propertyCount;
if (aliasId < 0 || aliasId >= metaData->aliasCount)
return;
connectAlias(aliasId);
}
+void QQmlVMEMetaObject::activate(QObject *object, int index, void **args)
+{
+ int signalOffset = cache->signalOffset();
+ int methodOffset = cache->methodOffset();
+
+ QMetaObject::activate(object, methodOffset, signalOffset, index - methodOffset, args);
+}
+
+QQmlVMEMetaObject *QQmlVMEMetaObject::getForProperty(QObject *o, int coreIndex)
+{
+ QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(o);
+ while (vme->propOffset() > coreIndex) {
+ Q_ASSERT(vme->parent.isT1());
+ vme = static_cast<QQmlVMEMetaObject *>(vme->parent.asT1());
+ }
+ return vme;
+}
+
+QQmlVMEMetaObject *QQmlVMEMetaObject::getForMethod(QObject *o, int coreIndex)
+{
+ QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(o);
+ while (vme->methodOffset() > coreIndex) {
+ Q_ASSERT(vme->parent.isT1());
+ vme = static_cast<QQmlVMEMetaObject *>(vme->parent.asT1());
+ }
+ return vme;
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index c9992471d4..9927de0b43 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -69,6 +69,7 @@
#include "qqmlcontext_p.h"
#include <private/qv8engine_p.h>
+#include <private/qflagpointer_p.h>
#include <private/qv8_p.h>
@@ -90,6 +91,7 @@ struct QQmlVMEMetaData
int contextIdx;
int propertyIdx;
int flags;
+ int notifySignal;
bool isObjectAlias() const {
return propertyIdx == -1;
@@ -156,7 +158,7 @@ class Q_AUTOTEST_EXPORT QQmlVMEMetaObject : public QAbstractDynamicMetaObject,
public QV8GCCallback::Node
{
public:
- QQmlVMEMetaObject(QObject *obj, const QMetaObject *other, const QQmlVMEMetaData *data);
+ QQmlVMEMetaObject(QObject *obj, QQmlPropertyCache *cache, const QQmlVMEMetaData *data);
~QQmlVMEMetaObject();
bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const;
@@ -169,22 +171,28 @@ public:
void connectAliasSignal(int index);
- static inline QQmlVMEMetaObject *get(const QObject *obj);
+ virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *o);
+
+ static inline QQmlVMEMetaObject *get(QObject *o);
+ static QQmlVMEMetaObject *getForProperty(QObject *o, int coreIndex);
+ static QQmlVMEMetaObject *getForMethod(QObject *o, int coreIndex);
protected:
virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
-private:
+public:
friend class QQmlVMEMetaObjectEndpoint;
friend class QQmlVMEVariantQObjectPtr;
QObject *object;
QQmlGuardedContextData ctxt;
+ QQmlPropertyCache *cache;
const QQmlVMEMetaData *metaData;
- int propOffset;
- int methodOffset;
+ inline int propOffset() const;
+ inline int methodOffset() const;
+ bool hasAssignedMetaObjectData;
QQmlVMEVariant *data;
QQmlVMEMetaObjectEndpoint *aliasEndpoints;
@@ -209,14 +217,15 @@ private:
QVariant readPropertyAsVariant(int);
void writeProperty(int, const QVariant &);
- QAbstractDynamicMetaObject *parent;
+ QBiPointer<QDynamicMetaObjectData, const QMetaObject> parent;
void listChanged(int);
class List : public QList<QObject*>
{
public:
- List(int lpi) : notifyIndex(lpi) {}
+ List(int lpi, QQmlVMEMetaObject *mo) : notifyIndex(lpi), mo(mo) {}
int notifyIndex;
+ QQmlVMEMetaObject *mo;
};
QList<List> listProperties;
@@ -225,11 +234,13 @@ private:
static QObject *list_at(QQmlListProperty<QObject> *, int);
static void list_clear(QQmlListProperty<QObject> *);
+ void activate(QObject *, int, void **);
+
friend class QV8GCCallback;
friend class QV8QObjectWrapper;
};
-QQmlVMEMetaObject *QQmlVMEMetaObject::get(const QObject *obj)
+QQmlVMEMetaObject *QQmlVMEMetaObject::get(QObject *obj)
{
if (obj) {
if (QQmlData *data = QQmlData::get(obj)) {
@@ -241,6 +252,16 @@ QQmlVMEMetaObject *QQmlVMEMetaObject::get(const QObject *obj)
return 0;
}
+int QQmlVMEMetaObject::propOffset() const
+{
+ return cache->propertyOffset();
+}
+
+int QQmlVMEMetaObject::methodOffset() const
+{
+ return cache->methodOffset();
+}
+
QT_END_NAMESPACE
#endif // QQMLVMEMETAOBJECT_P_H
diff --git a/src/qml/qml/v4/qv4bindings.cpp b/src/qml/qml/v4/qv4bindings.cpp
index 3c03edbca6..95eb0b9984 100644
--- a/src/qml/qml/v4/qv4bindings.cpp
+++ b/src/qml/qml/v4/qv4bindings.cpp
@@ -424,7 +424,7 @@ void QV4Bindings::run(Binding *binding, QQmlPropertyPrivate::WriteFlags flags)
QQmlData *data = QQmlData::get(*binding->target);
QQmlPropertyData *propertyData = (data && data->propertyCache ? data->propertyCache->property(binding->property) : 0);
- if (propertyData && propertyData->isVMEProperty()) {
+ if (propertyData && propertyData->isVarProperty()) {
// We will allocate a V8 handle in this conversion/store
v8::HandleScope handle_scope;
v8::Context::Scope context_scope(QQmlEnginePrivate::get(context->engine)->v8engine()->context());
@@ -2116,18 +2116,27 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
if (data.gettype() == QObjectStarType) {
if (QObject *dataObject = data.getQObject()) {
- const QMetaObject *dataMo = dataObject->metaObject();
+ QQmlMetaObject dataMo(dataObject);
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
- QMetaProperty receiver = output->metaObject()->property(instr->store.index);
- const QMetaObject *receiverMo = QQmlPropertyPrivate::rawMetaObjectForType(ep, receiver.userType());
+
+ QQmlMetaObject receiverMo;
+
+ if (QQmlData::get(output, false) && QQmlData::get(output, false)->propertyCache) {
+ QQmlPropertyData *receiver =
+ QQmlData::get(output, false)->propertyCache->property(instr->store.index);
+ receiverMo = ep->rawMetaObjectForType(receiver->propType);
+ } else {
+ QMetaProperty receiver = output->metaObject()->property(instr->store.index);
+ receiverMo = ep->rawMetaObjectForType(receiver.userType());
+ }
// Verify that these types are compatible
- if (!QQmlPropertyPrivate::canConvert(dataMo, receiverMo)) {
+ if (!QQmlMetaObject::canConvert(dataMo, receiverMo)) {
THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign ") +
- QLatin1String(dataMo->className()) +
+ QLatin1String(dataMo.className()) +
QLatin1String(" to ") +
- QLatin1String(receiverMo->className()));
+ QLatin1String(receiverMo.className()));
}
}
}
diff --git a/src/qml/qml/v4/qv4compiler.cpp b/src/qml/qml/v4/qv4compiler.cpp
index 1c163364a3..bac1f2c131 100644
--- a/src/qml/qml/v4/qv4compiler.cpp
+++ b/src/qml/qml/v4/qv4compiler.cpp
@@ -386,7 +386,7 @@ void QV4CompilerPrivate::visitName(IR::Name *e)
default:
if (propTy == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
regType = PODValueType;
- } else if (engine->metaObjectForType(propTy)) {
+ } else if (!engine->metaObjectForType(propTy).isNull()) {
regType = QObjectStarType;
} else {
if (qmlVerboseCompiler())
diff --git a/src/qml/qml/v4/qv4ir.cpp b/src/qml/qml/v4/qv4ir.cpp
index bb4a0d8df0..ed25f28fa3 100644
--- a/src/qml/qml/v4/qv4ir.cpp
+++ b/src/qml/qml/v4/qv4ir.cpp
@@ -496,7 +496,7 @@ Name *BasicBlock::NAME(Name *base, const QString &id, quint32 line, quint32 colu
return e;
}
-Name *BasicBlock::SYMBOL(Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, Name::Storage storage,
+Name *BasicBlock::SYMBOL(Type type, const QString &id, const QQmlMetaObject &meta, QQmlPropertyData *property, Name::Storage storage,
quint32 line, quint32 column)
{
Name *name = SYMBOL(/*base = */ 0, type, id, meta, property, line, column);
@@ -504,7 +504,7 @@ Name *BasicBlock::SYMBOL(Type type, const QString &id, const QMetaObject *meta,
return name;
}
-Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, Name::Storage storage,
+Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QQmlMetaObject &meta, QQmlPropertyData *property, Name::Storage storage,
quint32 line, quint32 column)
{
Name *name = function->pool->New<Name>();
@@ -516,7 +516,7 @@ Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaOb
return name;
}
-Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property,
+Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QQmlMetaObject &meta, QQmlPropertyData *property,
quint32 line, quint32 column)
{
Name *name = function->pool->New<Name>();
@@ -551,7 +551,7 @@ Name *BasicBlock::ATTACH_TYPE(const QString &id, const QQmlType *attachType, Nam
return name;
}
-Name *BasicBlock::MODULE_OBJECT(const QString &id, const QMetaObject *meta, Name::Storage storage,
+Name *BasicBlock::MODULE_OBJECT(const QString &id, const QQmlMetaObject &meta, Name::Storage storage,
quint32 line, quint32 column)
{
Name *name = function->pool->New<Name>();
diff --git a/src/qml/qml/v4/qv4ir_p.h b/src/qml/qml/v4/qv4ir_p.h
index 982acc5a44..9b36762356 100644
--- a/src/qml/qml/v4/qv4ir_p.h
+++ b/src/qml/qml/v4/qv4ir_p.h
@@ -275,10 +275,11 @@ struct Name: Expr {
Symbol symbol;
union {
void *ptr;
- const QMetaObject *meta;
const QQmlType *declarativeType;
const QQmlScript::Object *idObject;
};
+
+ QQmlMetaObject meta;
QQmlPropertyData *property;
Storage storage;
BuiltinSymbol builtin;
@@ -539,12 +540,12 @@ struct BasicBlock {
Name *NAME(const QString &id, quint32 line, quint32 column);
Name *NAME(Name *base, const QString &id, quint32 line, quint32 column);
- Name *SYMBOL(Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, Name::Storage storage, quint32 line, quint32 column);
- Name *SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, quint32 line, quint32 column);
- Name *SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, Name::Storage storage, quint32 line, quint32 column);
+ Name *SYMBOL(Type type, const QString &id, const QQmlMetaObject &meta, QQmlPropertyData *property, Name::Storage storage, quint32 line, quint32 column);
+ Name *SYMBOL(Name *base, Type type, const QString &id, const QQmlMetaObject &meta, QQmlPropertyData *property, quint32 line, quint32 column);
+ Name *SYMBOL(Name *base, Type type, const QString &id, const QQmlMetaObject &meta, QQmlPropertyData *property, Name::Storage storage, quint32 line, quint32 column);
Name *ID_OBJECT(const QString &id, const QQmlScript::Object *object, quint32 line, quint32 column);
Name *ATTACH_TYPE(const QString &id, const QQmlType *attachType, Name::Storage storage, quint32 line, quint32 column);
- Name *MODULE_OBJECT(const QString &id, const QMetaObject *meta, Name::Storage storage, quint32 line, quint32 column);
+ Name *MODULE_OBJECT(const QString &id, const QQmlMetaObject &meta, Name::Storage storage, quint32 line, quint32 column);
Expr *UNOP(AluOp op, Expr *expr);
Expr *BINOP(AluOp op, Expr *left, Expr *right);
diff --git a/src/qml/qml/v4/qv4irbuilder.cpp b/src/qml/qml/v4/qv4irbuilder.cpp
index 47acaaf67c..354a8cd70c 100644
--- a/src/qml/qml/v4/qv4irbuilder.cpp
+++ b/src/qml/qml/v4/qv4irbuilder.cpp
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
using namespace QQmlJS;
-static IR::Type irTypeFromVariantType(int t, QQmlEnginePrivate *engine, const QMetaObject * /* meta */)
+static IR::Type irTypeFromVariantType(int t, QQmlEnginePrivate *engine)
{
switch (t) {
case QMetaType::Bool:
@@ -81,7 +81,7 @@ static IR::Type irTypeFromVariantType(int t, QQmlEnginePrivate *engine, const QM
default:
if (t == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
return IR::SGAnchorLineType;
- } else if (engine->metaObjectForType(t)) {
+ } else if (!engine->metaObjectForType(t).isNull()) {
return IR::ObjectType;
} else if (t == qMetaTypeId<QJSValue>()) {
return IR::JSValueType;
@@ -125,9 +125,9 @@ bool QV4IRBuilder::operator()(QQmlJS::IR::Function *function,
// This is the only operation where variant is supported:
QQmlPropertyData *data = &m_expression->property->core;
if (data->propType == QMetaType::QVariant) {
- targetType = (data->isVMEProperty() ? IR::VarType : IR::VariantType);
+ targetType = (data->isVarProperty() ? IR::VarType : IR::VariantType);
} else {
- targetType = irTypeFromVariantType(data->propType, m_engine, 0);
+ targetType = irTypeFromVariantType(data->propType, m_engine);
}
if (targetType != r.type()) {
@@ -462,8 +462,7 @@ bool QV4IRBuilder::visit(AST::IdentifierExpression *ast)
if (m_expression->context != m_expression->component) {
// RootStorage is more efficient than ScopeStorage, so prefer that if they are the same
QQmlPropertyCache *cache = m_expression->context->synthCache;
- const QMetaObject *metaObject = m_expression->context->metaObject();
- if (!cache) cache = m_engine->cache(metaObject);
+ if (!cache) cache = m_expression->context->metatype;
QQmlPropertyData *data = cache->property(name);
@@ -475,16 +474,15 @@ bool QV4IRBuilder::visit(AST::IdentifierExpression *ast)
}
if (data && !data->isFunction()) {
- IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
- _expr.code = _block->SYMBOL(irType, name, metaObject, data, IR::Name::ScopeStorage, line, column);
+ IR::Type irType = irTypeFromVariantType(data->propType, m_engine);
+ _expr.code = _block->SYMBOL(irType, name, QQmlMetaObject(), data, IR::Name::ScopeStorage, line, column);
found = true;
}
}
if (!found) {
QQmlPropertyCache *cache = m_expression->component->synthCache;
- const QMetaObject *metaObject = m_expression->component->metaObject();
- if (!cache) cache = m_engine->cache(metaObject);
+ if (!cache) cache = m_expression->component->metatype;
QQmlPropertyData *data = cache->property(name);
@@ -496,8 +494,8 @@ bool QV4IRBuilder::visit(AST::IdentifierExpression *ast)
}
if (data && !data->isFunction()) {
- IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
- _expr.code = _block->SYMBOL(irType, name, metaObject, data, IR::Name::RootStorage, line, column);
+ IR::Type irType = irTypeFromVariantType(data->propType, m_engine);
+ _expr.code = _block->SYMBOL(irType, name, QQmlMetaObject(), data, IR::Name::RootStorage, line, column);
found = true;
}
}
@@ -624,7 +622,7 @@ bool QV4IRBuilder::visit(AST::FieldMemberExpression *ast)
return false; // We don't know enough about this property
}
- IR::Type irType = irTypeFromVariantType(data->propType, m_engine, attachedMeta);
+ IR::Type irType = irTypeFromVariantType(data->propType, m_engine);
_expr.code = _block->SYMBOL(baseName, irType, name, attachedMeta, data, line, column);
}
break;
@@ -634,7 +632,7 @@ bool QV4IRBuilder::visit(AST::FieldMemberExpression *ast)
QByteArray utf8Name = name.toUtf8();
const char *enumName = utf8Name.constData();
- const QMetaObject *meta = baseName->meta;
+ const QMetaObject *meta = baseName->meta.metaObject(); // XXX - firstCppMetaObject
bool found = false;
for (int ii = 0; !found && ii < meta->enumeratorCount(); ++ii) {
QMetaEnum e = meta->enumerator(ii);
@@ -649,7 +647,7 @@ bool QV4IRBuilder::visit(AST::FieldMemberExpression *ast)
qWarning() << "*** unresolved enum:"
<< (*baseName->id + QLatin1Char('.') + ast->name.toString());
} else {
- QQmlPropertyCache *cache = m_engine->cache(baseName->meta);
+ QQmlPropertyCache *cache = baseName->meta.propertyCache(m_engine);
if (!cache) return false;
QQmlPropertyData *data = cache->property(name);
@@ -663,7 +661,7 @@ bool QV4IRBuilder::visit(AST::FieldMemberExpression *ast)
return false; // We don't know enough about this property
}
- IR::Type irType = irTypeFromVariantType(data->propType, m_engine, baseName->meta);
+ IR::Type irType = irTypeFromVariantType(data->propType, m_engine);
_expr.code = _block->SYMBOL(baseName, irType, name, baseName->meta, data, line, column);
}
}
@@ -672,7 +670,7 @@ bool QV4IRBuilder::visit(AST::FieldMemberExpression *ast)
case IR::Name::IdObject: {
const QQmlScript::Object *idObject = baseName->idObject;
QQmlPropertyCache *cache =
- idObject->synthCache?idObject->synthCache:m_engine->cache(idObject->metaObject());
+ idObject->synthCache?idObject->synthCache:idObject->metatype;
QQmlPropertyData *data = cache->property(name);
@@ -686,16 +684,16 @@ bool QV4IRBuilder::visit(AST::FieldMemberExpression *ast)
return false;
}
- IR::Type irType = irTypeFromVariantType(data->propType, m_engine, idObject->metaObject());
- _expr.code = _block->SYMBOL(baseName, irType, name,
- idObject->metaObject(), data, line, column);
+ IR::Type irType = irTypeFromVariantType(data->propType, m_engine);
+ _expr.code = _block->SYMBOL(baseName, irType, name, QQmlMetaObject(), data, line, column);
}
break;
case IR::Name::Property:
- if (baseName->type == IR::ObjectType && baseName->meta && baseName->property->isFinal()) {
- const QMetaObject *meta = m_engine->metaObjectForType(baseName->property->propType);
- QQmlPropertyCache *cache = m_engine->cache(meta);
+ if (baseName->type == IR::ObjectType && !baseName->meta.isNull() &&
+ baseName->property->isFinal()) {
+ QQmlMetaObject meta = m_engine->metaObjectForType(baseName->property->propType);
+ QQmlPropertyCache *cache = meta.propertyCache(m_engine);
if (!cache)
return false;
@@ -707,7 +705,7 @@ bool QV4IRBuilder::visit(AST::FieldMemberExpression *ast)
return false; // We don't know enough about this property
}
- IR::Type irType = irTypeFromVariantType(data->propType, m_engine, meta);
+ IR::Type irType = irTypeFromVariantType(data->propType, m_engine);
_expr.code = _block->SYMBOL(baseName, irType, name,
meta, data, line, column);
}
diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp
index d7e55e2816..0c656631f7 100644
--- a/src/qml/qml/v8/qv8qobjectwrapper.cpp
+++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp
@@ -535,7 +535,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject
return v8::Handle<v8::Value>();
}
- if (result->isFunction() && !result->isVMEProperty()) {
+ if (result->isFunction() && !result->isVarProperty()) {
if (result->isVMEFunction()) {
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
@@ -576,7 +576,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject
if (ep && !result->isConstant())
ep->captureProperty(object, result->coreIndex, result->notifyIndex);
- if (result->isVMEProperty()) {
+ if (result->isVarProperty()) {
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
return vmemo->vmeProperty(result->coreIndex);
@@ -594,7 +594,7 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QQmlPropert
QQmlBinding *newBinding = 0;
if (value->IsFunction()) {
if (value->ToObject()->GetHiddenValue(engine->bindingFlagKey()).IsEmpty()) {
- if (!property->isVMEProperty() && property->propType != qMetaTypeId<QJSValue>()) {
+ if (!property->isVarProperty() && property->propType != qMetaTypeId<QJSValue>()) {
// assigning a JS function to a non var or QJSValue property or is not allowed.
QString error = QLatin1String("Cannot assign JavaScript function to ") +
QLatin1String(QMetaType::typeName(property->propType));
@@ -626,7 +626,7 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QQmlPropert
if (oldBinding)
oldBinding->destroy();
- if (!newBinding && property->isVMEProperty()) {
+ if (!newBinding && property->isVarProperty()) {
// allow assignment of "special" values (null, undefined, function) to var properties
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
@@ -641,7 +641,6 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QQmlPropert
void *argv[] = { &o, 0, &status, &flags }; \
QMetaObject::metacall(object, QMetaObject::WriteProperty, property->coreIndex, argv);
-
if (value->IsNull() && property->isQObject()) {
PROPERTY_STORE(QObject*, 0);
} else if (value->IsUndefined() && property->isResettable()) {
@@ -669,7 +668,7 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QQmlPropert
PROPERTY_STORE(double, double(value->ToNumber()->Value()));
} else if (property->propType == QMetaType::QString && value->IsString()) {
PROPERTY_STORE(QString, engine->toString(value->ToString()));
- } else if (property->isVMEProperty()) {
+ } else if (property->isVarProperty()) {
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
vmemo->setVMEProperty(property->coreIndex, value);
@@ -2146,18 +2145,18 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8::Val
} else if (v.canConvert(callType)) {
*qvariantPtr = v;
qvariantPtr->convert(callType);
- } else if (const QMetaObject *mo = ep ? ep->rawMetaObjectForType(callType) : 0) {
- QObject *obj = ep->toQObject(v);
-
- if (obj) {
- const QMetaObject *objMo = obj->metaObject();
- while (objMo && objMo != mo) objMo = objMo->superClass();
- if (!objMo) obj = 0;
- }
-
- *qvariantPtr = QVariant(callType, &obj);
} else {
- *qvariantPtr = QVariant(callType, (void *)0);
+ QQmlMetaObject mo = ep ? ep->rawMetaObjectForType(callType) : QQmlMetaObject();
+ if (!mo.isNull()) {
+ QObject *obj = ep->toQObject(v);
+
+ if (obj != 0 && !QQmlMetaObject::canConvert(obj, mo))
+ obj = 0;
+
+ *qvariantPtr = QVariant(callType, &obj);
+ } else {
+ *qvariantPtr = QVariant(callType, (void *)0);
+ }
}
}
}
diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp
index b4efa508b3..5b48a6fc85 100644
--- a/src/quick/items/qquickborderimage.cpp
+++ b/src/quick/items/qquickborderimage.cpp
@@ -316,7 +316,8 @@ void QQuickBorderImage::load()
} else {
QNetworkRequest req(d->url);
d->sciReply = qmlEngine(this)->networkAccessManager()->get(req);
- FAST_CONNECT(d->sciReply, SIGNAL(finished()), this, SLOT(sciRequestFinished()))
+ qmlobject_connect(d->sciReply, QNetworkReply, SIGNAL(finished()),
+ this, QQuickBorderImage, SLOT(sciRequestFinished()))
}
} else {
diff --git a/src/quick/items/qquickborderimage_p_p.h b/src/quick/items/qquickborderimage_p_p.h
index 07a62b4d29..a55bd56cea 100644
--- a/src/quick/items/qquickborderimage_p_p.h
+++ b/src/quick/items/qquickborderimage_p_p.h
@@ -84,7 +84,8 @@ public:
Q_Q(QQuickBorderImage);
if (!border) {
border = new QQuickScaleGrid(q);
- FAST_CONNECT(border, SIGNAL(borderChanged()), q, SLOT(doUpdate()))
+ qmlobject_connect(border, QQuickScaleGrid, SIGNAL(borderChanged()),
+ q, QQuickBorderImage, SLOT(doUpdate()))
}
return border;
}
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index e8558de232..e4e0799d89 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -208,7 +208,8 @@ void QQuickFlickablePrivate::init()
Q_Q(QQuickFlickable);
QQml_setParent_noEvent(contentItem, q);
contentItem->setParentItem(q);
- FAST_CONNECT(&timeline, SIGNAL(completed()), q, SLOT(movementEnding()))
+ qmlobject_connect(&timeline, QQuickTimeLine, SIGNAL(completed()),
+ q, QQuickFlickable, SLOT(movementEnding()))
q->setAcceptedMouseButtons(Qt::LeftButton);
q->setFiltersChildMouseEvents(true);
QQuickItemPrivate *viewportPrivate = QQuickItemPrivate::get(contentItem);
@@ -1420,8 +1421,7 @@ void QQuickFlickable::cancelFlick()
void QQuickFlickablePrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o)
{
- QQuickItem *i = qobject_cast<QQuickItem *>(o);
- if (i) {
+ if (QQuickItem *i = qmlobject_cast<QQuickItem *>(o)) {
i->setParentItem(static_cast<QQuickFlickablePrivate*>(prop->data)->contentItem);
} else {
o->setParent(prop->object); // XXX todo - do we want this?
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index b7e6f075ad..e83fee3583 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -566,7 +566,7 @@ void QQuickItemKeyFilter::componentComplete()
QQuickKeyNavigationAttached::QQuickKeyNavigationAttached(QObject *parent)
: QObject(*(new QQuickKeyNavigationAttachedPrivate), parent),
- QQuickItemKeyFilter(qobject_cast<QQuickItem*>(parent))
+ QQuickItemKeyFilter(qmlobject_cast<QQuickItem*>(parent))
{
m_processPost = true;
}
@@ -1305,11 +1305,11 @@ bool QQuickKeysAttached::isConnected(const char *signalName)
QQuickKeysAttached::QQuickKeysAttached(QObject *parent)
: QObject(*(new QQuickKeysAttachedPrivate), parent),
- QQuickItemKeyFilter(qobject_cast<QQuickItem*>(parent))
+ QQuickItemKeyFilter(qmlobject_cast<QQuickItem*>(parent))
{
Q_D(QQuickKeysAttached);
m_processPost = false;
- d->item = qobject_cast<QQuickItem*>(parent);
+ d->item = qmlobject_cast<QQuickItem*>(parent);
}
QQuickKeysAttached::~QQuickKeysAttached()
@@ -1604,7 +1604,7 @@ void QQuickItemPrivate::setImplicitLayoutMirror(bool mirror, bool inherit)
if (isMirrorImplicit)
setLayoutMirror(inherit ? inheritedLayoutMirror : false);
for (int i = 0; i < childItems.count(); ++i) {
- if (QQuickItem *child = qobject_cast<QQuickItem *>(childItems.at(i))) {
+ if (QQuickItem *child = qmlobject_cast<QQuickItem *>(childItems.at(i))) {
QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
childPrivate->setImplicitLayoutMirror(inheritedLayoutMirror, inheritMirrorFromParent);
}
@@ -2496,14 +2496,7 @@ void QQuickItemPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o)
QQuickItem *that = static_cast<QQuickItem *>(prop->object);
- // This test is measurably (albeit only slightly) faster than qobject_cast<>()
- const QMetaObject *mo = o->metaObject();
- while (mo && mo != &QQuickItem::staticMetaObject) {
- mo = mo->d.superdata;
- }
-
- if (mo) {
- QQuickItem *item = static_cast<QQuickItem *>(o);
+ if (QQuickItem *item = qmlobject_cast<QQuickItem *>(o)) {
item->setParentItem(that);
} else {
if (o->inherits("QGraphicsItem"))
@@ -3696,8 +3689,8 @@ QQuickStateGroup *QQuickItemPrivate::_states()
_stateGroup = new QQuickStateGroup;
if (!componentComplete)
_stateGroup->classBegin();
- FAST_CONNECT(_stateGroup, SIGNAL(stateChanged(QString)),
- q, SIGNAL(stateChanged(QString)))
+ qmlobject_connect(_stateGroup, QQuickStateGroup, SIGNAL(stateChanged(QString)),
+ q, QQuickItem, SIGNAL(stateChanged(QString)))
}
return _stateGroup;
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index 3348122758..bb1305545e 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -88,11 +88,11 @@
static QQmlPrivate::AutoParentResult qquickitem_autoParent(QObject *obj, QObject *parent)
{
- QQuickItem *item = qobject_cast<QQuickItem *>(obj);
+ QQuickItem *item = qmlobject_cast<QQuickItem *>(obj);
if (!item)
return QQmlPrivate::IncompatibleObject;
- QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent);
+ QQuickItem *parentItem = qmlobject_cast<QQuickItem *>(parent);
if (!parentItem)
return QQmlPrivate::IncompatibleParent;
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index 1d01cb10bc..fdc3db9fb7 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -588,7 +588,7 @@ void QQuickLoaderPrivate::setInitialState(QObject *obj)
{
Q_Q(QQuickLoader);
- QQuickItem *item = qobject_cast<QQuickItem*>(obj);
+ QQuickItem *item = qmlobject_cast<QQuickItem*>(obj);
if (item) {
// If the item doesn't have an explicit size, but the Loader
// does, then set the item's size now before bindings are
@@ -625,7 +625,7 @@ void QQuickLoaderPrivate::incubatorStateChanged(QQmlIncubator::Status status)
if (status == QQmlIncubator::Ready) {
QObject *obj = incubator->object();
- item = qobject_cast<QQuickItem*>(obj);
+ item = qmlobject_cast<QQuickItem*>(obj);
if (item) {
emit q->itemChanged();
initResize();
diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp
index 1bc3a3a9ab..18c8cee349 100644
--- a/src/quick/items/qquickpathview.cpp
+++ b/src/quick/items/qquickpathview.cpp
@@ -138,9 +138,11 @@ void QQuickPathViewPrivate::init()
q->setAcceptedMouseButtons(Qt::LeftButton);
q->setFlag(QQuickItem::ItemIsFocusScope);
q->setFiltersChildMouseEvents(true);
- FAST_CONNECT(&tl, SIGNAL(updated()), q, SLOT(ticked()))
+ qmlobject_connect(&tl, QQuickTimeLine, SIGNAL(updated()),
+ q, QQuickPathView, SLOT(ticked()))
timer.invalidate();
- FAST_CONNECT(&tl, SIGNAL(completed()), q, SLOT(movementEnding()))
+ qmlobject_connect(&tl, QQuickTimeLine, SIGNAL(completed()),
+ q, QQuickPathView, SLOT(movementEnding()))
}
QQuickItem *QQuickPathViewPrivate::getItem(int modelIndex, qreal z, bool onPath)
@@ -578,10 +580,12 @@ void QQuickPathView::setModel(const QVariant &model)
return;
if (d->model) {
- disconnect(d->model, SIGNAL(modelUpdated(QQuickChangeSet,bool)),
- this, SLOT(modelUpdated(QQuickChangeSet,bool)));
- disconnect(d->model, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(createdItem(int,QQuickItem*)));
- disconnect(d->model, SIGNAL(initItem(int,QQuickItem*)), this, SLOT(initItem(int,QQuickItem*)));
+ qmlobject_disconnect(d->model, QQuickVisualModel, SIGNAL(modelUpdated(QQuickChangeSet,bool)),
+ this, QQuickPathView, SLOT(modelUpdated(QQuickChangeSet,bool)));
+ qmlobject_disconnect(d->model, QQuickVisualModel, SIGNAL(createdItem(int,QQuickItem*)),
+ this, QQuickPathView, SLOT(createdItem(int,QQuickItem*)));
+ qmlobject_disconnect(d->model, QQuickVisualModel, SIGNAL(initItem(int,QQuickItem*)),
+ this, QQuickPathView, SLOT(initItem(int,QQuickItem*)));
for (int i=0; i<d->items.count(); i++){
QQuickItem *p = d->items[i];
d->releaseItem(p);
@@ -610,10 +614,12 @@ void QQuickPathView::setModel(const QVariant &model)
}
d->modelCount = 0;
if (d->model) {
- connect(d->model, SIGNAL(modelUpdated(QQuickChangeSet,bool)),
- this, SLOT(modelUpdated(QQuickChangeSet,bool)));
- connect(d->model, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(createdItem(int,QQuickItem*)));
- connect(d->model, SIGNAL(initItem(int,QQuickItem*)), this, SLOT(initItem(int,QQuickItem*)));
+ qmlobject_connect(d->model, QQuickVisualModel, SIGNAL(modelUpdated(QQuickChangeSet,bool)),
+ this, QQuickPathView, SLOT(modelUpdated(QQuickChangeSet,bool)));
+ qmlobject_connect(d->model, QQuickVisualModel, SIGNAL(createdItem(int,QQuickItem*)),
+ this, QQuickPathView, SLOT(createdItem(int,QQuickItem*)));
+ qmlobject_connect(d->model, QQuickVisualModel, SIGNAL(initItem(int,QQuickItem*)),
+ this, QQuickPathView, SLOT(initItem(int,QQuickItem*)));
d->modelCount = d->model->count();
if (d->model->count())
d->offset = qmlMod(d->offset, qreal(d->model->count()));
@@ -656,9 +662,11 @@ void QQuickPathView::setPath(QQuickPath *path)
if (d->path == path)
return;
if (d->path)
- disconnect(d->path, SIGNAL(changed()), this, SLOT(pathUpdated()));
+ qmlobject_disconnect(d->path, QQuickPath, SIGNAL(changed()),
+ this, QQuickPathView, SLOT(pathUpdated()));
d->path = path;
- connect(d->path, SIGNAL(changed()), this, SLOT(pathUpdated()));
+ qmlobject_connect(d->path, QQuickPath, SIGNAL(changed()),
+ this, QQuickPathView, SLOT(pathUpdated()));
if (d->isValid() && isComponentComplete()) {
d->clear();
if (d->attType) {
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index b6ccc5ec17..b61d329e5f 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -1131,7 +1131,8 @@ void QQuickTextPrivate::ensureDoc()
extra.value().doc = new QQuickTextDocumentWithImageResources(q);
extra->doc->setDocumentMargin(0);
extra->doc->setBaseUrl(q->baseUrl());
- FAST_CONNECT(extra->doc, SIGNAL(imagesLoaded()), q, SLOT(q_imagesLoaded()));
+ qmlobject_connect(extra->doc, QQuickTextDocumentWithImageResources, SIGNAL(imagesLoaded()),
+ q, QQuickText, SLOT(q_imagesLoaded()));
}
}
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 2d16c02bb2..a3dd772718 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -1746,21 +1746,21 @@ void QQuickTextEditPrivate::init()
control->setAcceptRichText(false);
control->setCursorIsFocusIndicator(true);
- FAST_CONNECT(control, SIGNAL(updateRequest(QRectF)), q, SLOT(updateDocument()));
- FAST_CONNECT(control, SIGNAL(updateCursorRequest()), q, SLOT(updateCursor()));
- FAST_CONNECT(control, SIGNAL(textChanged()), q, SLOT(q_textChanged()));
- FAST_CONNECT(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged()));
- FAST_CONNECT(control, SIGNAL(selectionChanged()), q, SLOT(updateSelectionMarkers()));
- FAST_CONNECT(control, SIGNAL(cursorPositionChanged()), q, SLOT(updateSelectionMarkers()));
- FAST_CONNECT(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged()));
- FAST_CONNECT(control, SIGNAL(cursorRectangleChanged()), q, SLOT(moveCursorDelegate()));
- FAST_CONNECT(control, SIGNAL(linkActivated(QString)), q, SIGNAL(linkActivated(QString)));
+ qmlobject_connect(control, QQuickTextControl, SIGNAL(updateRequest(QRectF)), q, QQuickTextEdit, SLOT(updateDocument()));
+ qmlobject_connect(control, QQuickTextControl, SIGNAL(updateCursorRequest()), q, QQuickTextEdit, SLOT(updateCursor()));
+ qmlobject_connect(control, QQuickTextControl, SIGNAL(textChanged()), q, QQuickTextEdit, SLOT(q_textChanged()));
+ qmlobject_connect(control, QQuickTextControl, SIGNAL(selectionChanged()), q, QQuickTextEdit, SIGNAL(selectionChanged()));
+ qmlobject_connect(control, QQuickTextControl, SIGNAL(selectionChanged()), q, QQuickTextEdit, SLOT(updateSelectionMarkers()));
+ qmlobject_connect(control, QQuickTextControl, SIGNAL(cursorPositionChanged()), q, QQuickTextEdit, SLOT(updateSelectionMarkers()));
+ qmlobject_connect(control, QQuickTextControl, SIGNAL(cursorPositionChanged()), q, QQuickTextEdit, SIGNAL(cursorPositionChanged()));
+ qmlobject_connect(control, QQuickTextControl, SIGNAL(cursorRectangleChanged()), q, QQuickTextEdit, SLOT(moveCursorDelegate()));
+ qmlobject_connect(control, QQuickTextControl, SIGNAL(linkActivated(QString)), q, QQuickTextEdit, SIGNAL(linkActivated(QString)));
#ifndef QT_NO_CLIPBOARD
- FAST_CONNECT(QGuiApplication::clipboard(), SIGNAL(dataChanged()), q, SLOT(q_canPasteChanged()));
+ qmlobject_connect(QGuiApplication::clipboard(), QClipboard, SIGNAL(dataChanged()), q, QQuickTextEdit, SLOT(q_canPasteChanged()));
#endif
- FAST_CONNECT(document, SIGNAL(undoAvailable(bool)), q, SIGNAL(canUndoChanged()));
- FAST_CONNECT(document, SIGNAL(redoAvailable(bool)), q, SIGNAL(canRedoChanged()));
- FAST_CONNECT(document, SIGNAL(imagesLoaded()), q, SLOT(updateSize()));
+ qmlobject_connect(document, QQuickTextDocumentWithImageResources, SIGNAL(undoAvailable(bool)), q, QQuickTextEdit, SIGNAL(canUndoChanged()));
+ qmlobject_connect(document, QQuickTextDocumentWithImageResources, SIGNAL(redoAvailable(bool)), q, QQuickTextEdit, SIGNAL(canRedoChanged()));
+ qmlobject_connect(document, QQuickTextDocumentWithImageResources, SIGNAL(imagesLoaded()), q, QQuickTextEdit, SLOT(updateSize()));
document->setDefaultFont(font);
document->setDocumentMargin(textMargin);
diff --git a/src/quick/items/qquickvisualadaptormodel.cpp b/src/quick/items/qquickvisualadaptormodel.cpp
index d772d67c18..99c44e329c 100644
--- a/src/quick/items/qquickvisualadaptormodel.cpp
+++ b/src/quick/items/qquickvisualadaptormodel.cpp
@@ -996,29 +996,29 @@ void QQuickVisualAdaptorModel::setModel(const QVariant &variant, QQuickVisualDat
if (QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(object)) {
accessors = new VDMAbstractItemModelDataType(this);
- FAST_CONNECT(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
- vdm, SLOT(_q_rowsInserted(QModelIndex,int,int)));
- FAST_CONNECT(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- vdm, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
- FAST_CONNECT(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- vdm, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
- FAST_CONNECT(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- vdm, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
- FAST_CONNECT(model, SIGNAL(modelReset()),
- vdm, SLOT(_q_modelReset()));
- FAST_CONNECT(model, SIGNAL(layoutChanged()),
- vdm, SLOT(_q_layoutChanged()));
+ qmlobject_connect(model, QAbstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
+ vdm, QQuickVisualDataModel, SLOT(_q_rowsInserted(QModelIndex,int,int)));
+ qmlobject_connect(model, QAbstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ vdm, QQuickVisualDataModel, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
+ qmlobject_connect(model, QAbstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ vdm, QQuickVisualDataModel, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
+ qmlobject_connect(model, QAbstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
+ vdm, QQuickVisualDataModel, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
+ qmlobject_connect(model, QAbstractItemModel, SIGNAL(modelReset()),
+ vdm, QQuickVisualDataModel, SLOT(_q_modelReset()));
+ qmlobject_connect(model, QAbstractItemModel, SIGNAL(layoutChanged()),
+ vdm, QQuickVisualDataModel, SLOT(_q_layoutChanged()));
} else if (QListModelInterface *model = qobject_cast<QListModelInterface *>(object)) {
accessors = new VDMListModelInterfaceDataType(this);
- FAST_CONNECT(model, SIGNAL(itemsChanged(int,int,QList<int>)),
- vdm, SLOT(_q_itemsChanged(int,int,QList<int>)));
- FAST_CONNECT(model, SIGNAL(itemsInserted(int,int)),
- vdm, SLOT(_q_itemsInserted(int,int)));
- FAST_CONNECT(model, SIGNAL(itemsRemoved(int,int)),
- vdm, SLOT(_q_itemsRemoved(int,int)));
- FAST_CONNECT(model, SIGNAL(itemsMoved(int,int,int)),
- vdm, SLOT(_q_itemsMoved(int,int,int)));
+ qmlobject_connect(model, QListModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
+ vdm, QQuickVisualDataModel, SLOT(_q_itemsChanged(int,int,QList<int>)));
+ qmlobject_connect(model, QListModelInterface, SIGNAL(itemsInserted(int,int)),
+ vdm, QQuickVisualDataModel, SLOT(_q_itemsInserted(int,int)));
+ qmlobject_connect(model, QListModelInterface, SIGNAL(itemsRemoved(int,int)),
+ vdm, QQuickVisualDataModel, SLOT(_q_itemsRemoved(int,int)));
+ qmlobject_connect(model, QListModelInterface, SIGNAL(itemsMoved(int,int,int)),
+ vdm, QQuickVisualDataModel, SLOT(_q_itemsMoved(int,int,int)));
} else {
accessors = new VDMObjectDelegateDataType;
}
diff --git a/src/quick/items/qquickvisualdatamodel.cpp b/src/quick/items/qquickvisualdatamodel.cpp
index 79ddeca6e9..d202c61112 100644
--- a/src/quick/items/qquickvisualdatamodel.cpp
+++ b/src/quick/items/qquickvisualdatamodel.cpp
@@ -430,7 +430,7 @@ QQuickVisualDataModel::ReleaseFlags QQuickVisualDataModelPrivate::release(QObjec
if (QQuickVisualDataModelItem *cacheItem = QQuickVisualDataModelItem::dataForObject(object)) {
if (cacheItem->releaseObject()) {
cacheItem->destroyObject();
- if (QQuickItem *item = qobject_cast<QQuickItem *>(object))
+ if (QQuickItem *item = qmlobject_cast<QQuickItem *>(object))
emitDestroyingItem(item);
if (cacheItem->incubationTask) {
releaseIncubator(cacheItem->incubationTask);
@@ -477,9 +477,9 @@ void QQuickVisualDataModel::cancel(int index)
if (cacheItem->object() && !cacheItem->isObjectReferenced()) {
QObject *object = cacheItem->object();
cacheItem->destroyObject();
- if (QQuickPackage *package = qobject_cast<QQuickPackage *>(object))
+ if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
d->emitDestroyingPackage(package);
- else if (QQuickItem *item = qobject_cast<QQuickItem *>(object))
+ else if (QQuickItem *item = qmlobject_cast<QQuickItem *>(object))
d->emitDestroyingItem(item);
cacheItem->scriptRef -= 1;
}
@@ -741,7 +741,7 @@ void QQuickVisualDataModelPrivate::incubatorStatusChanged(QVDMIncubationTask *in
if (status == QQmlIncubator::Ready) {
incubationTask->incubating = 0;
releaseIncubator(incubationTask);
- if (QQuickPackage *package = qobject_cast<QQuickPackage *>(cacheItem->object()))
+ if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object()))
emitCreatedPackage(cacheItem, package);
else if (QQuickItem *item = qobject_cast<QQuickItem *>(cacheItem->object()))
emitCreatedItem(cacheItem, item);
@@ -773,9 +773,9 @@ void QQuickVisualDataModelPrivate::setInitialState(QVDMIncubationTask *incubatio
QQuickVisualDataModelItem *cacheItem = incubationTask->incubating;
cacheItem->setObject(o);
- if (QQuickPackage *package = qobject_cast<QQuickPackage *>(cacheItem->object()))
+ if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object()))
emitInitPackage(cacheItem, package);
- else if (QQuickItem *item = qobject_cast<QQuickItem *>(cacheItem->object()))
+ else if (QQuickItem *item = qmlobject_cast<QQuickItem *>(cacheItem->object()))
emitInitItem(cacheItem, item);
}
@@ -868,7 +868,7 @@ QQuickItem *QQuickVisualDataModel::item(int index, bool asynchronous)
if (!object)
return 0;
- if (QQuickItem *item = qobject_cast<QQuickItem *>(object))
+ if (QQuickItem *item = qmlobject_cast<QQuickItem *>(object))
return item;
d->release(object);
@@ -1117,9 +1117,9 @@ void QQuickVisualDataModelPrivate::itemsRemoved(
if (remove.inGroup(Compositor::Persisted) && cacheItem->objectRef == 0 && cacheItem->object()) {
QObject *object = cacheItem->object();
cacheItem->destroyObject();
- if (QQuickPackage *package = qobject_cast<QQuickPackage *>(object))
+ if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
emitDestroyingPackage(package);
- else if (QQuickItem *item = qobject_cast<QQuickItem *>(object))
+ else if (QQuickItem *item = qmlobject_cast<QQuickItem *>(object))
emitDestroyingItem(item);
cacheItem->setObject(0);
cacheItem->scriptRef -= 1;
@@ -2767,11 +2767,11 @@ QQuickItem *QQuickVisualPartsModel::item(int index, bool asynchronous)
QObject *object = model->object(m_compositorGroup, index, asynchronous, true);
- if (QQuickPackage *package = qobject_cast<QQuickPackage *>(object)) {
+ if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object)) {
QObject *part = package->part(m_part);
if (!part)
return 0;
- if (QQuickItem *item = qobject_cast<QQuickItem *>(part)) {
+ if (QQuickItem *item = qmlobject_cast<QQuickItem *>(part)) {
m_packaged.insertMulti(item, package);
return item;
}
@@ -2830,19 +2830,19 @@ int QQuickVisualPartsModel::indexOf(QQuickItem *item, QObject *) const
void QQuickVisualPartsModel::createdPackage(int index, QQuickPackage *package)
{
- if (QQuickItem *item = qobject_cast<QQuickItem *>(package->part(m_part)))
+ if (QQuickItem *item = qmlobject_cast<QQuickItem *>(package->part(m_part)))
emit createdItem(index, item);
}
void QQuickVisualPartsModel::initPackage(int index, QQuickPackage *package)
{
- if (QQuickItem *item = qobject_cast<QQuickItem *>(package->part(m_part)))
+ if (QQuickItem *item = qmlobject_cast<QQuickItem *>(package->part(m_part)))
emit initItem(index, item);
}
void QQuickVisualPartsModel::destroyingPackage(QQuickPackage *package)
{
- if (QQuickItem *item = qobject_cast<QQuickItem *>(package->part(m_part))) {
+ if (QQuickItem *item = qmlobject_cast<QQuickItem *>(package->part(m_part))) {
Q_ASSERT(!m_packaged.contains(item));
emit destroyingItem(item);
item->setParentItem(0);
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index 77d4809ac6..4544df23fa 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -1601,10 +1601,8 @@ QQuickAnimationGroup::QQuickAnimationGroup(QQuickAnimationGroupPrivate &dd, QObj
void QQuickAnimationGroupPrivate::append_animation(QQmlListProperty<QQuickAbstractAnimation> *list, QQuickAbstractAnimation *a)
{
- QQuickAnimationGroup *q = qobject_cast<QQuickAnimationGroup *>(list->object);
- if (q) {
+ if (QQuickAnimationGroup *q = qmlobject_cast<QQuickAnimationGroup *>(list->object))
a->setGroup(q);
- }
}
void QQuickAnimationGroupPrivate::clear_animation(QQmlListProperty<QQuickAbstractAnimation> *list)
diff --git a/src/quick/util/qquickconnections.cpp b/src/quick/util/qquickconnections.cpp
index d3c33611e2..934c59bc0f 100644
--- a/src/quick/util/qquickconnections.cpp
+++ b/src/quick/util/qquickconnections.cpp
@@ -279,7 +279,7 @@ void QQuickConnections::connectSignals()
QQmlProperty prop(target(), propName);
if (prop.isValid() && (prop.type() & QQmlProperty::SignalProperty)) {
QQmlBoundSignal *signal =
- new QQmlBoundSignal(target(), prop.method(), this, qmlEngine(this));
+ new QQmlBoundSignal(target(), prop.index(), this, qmlEngine(this));
QString location;
QQmlContextData *ctxtdata = 0;
diff --git a/tests/auto/qml/qqmlcpputils/qqmlcpputils.pro b/tests/auto/qml/qqmlcpputils/qqmlcpputils.pro
index 1c088860e5..847665b8f4 100644
--- a/tests/auto/qml/qqmlcpputils/qqmlcpputils.pro
+++ b/tests/auto/qml/qqmlcpputils/qqmlcpputils.pro
@@ -6,4 +6,4 @@ SOURCES += tst_qqmlcpputils.cpp
CONFIG += parallel_test
-QT += core-private gui-private qml-private testlib
+QT += core-private gui-private qml-private testlib v8-private
diff --git a/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp b/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp
index 186b82a0a8..4189f441a2 100644
--- a/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp
+++ b/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp
@@ -73,7 +73,7 @@ void tst_qqmlcpputils::fastConnect()
{
{
MyObject *obj = new MyObject;
- FAST_CONNECT(obj, SIGNAL(signal1()), obj, SLOT(slot1()));
+ qmlobject_connect(obj, MyObject, SIGNAL(signal1()), obj, MyObject, SLOT(slot1()));
obj->signal1();
QCOMPARE(obj->slotCount, 1);
@@ -83,7 +83,7 @@ void tst_qqmlcpputils::fastConnect()
{
MyObject obj;
- FAST_CONNECT(&obj, SIGNAL(signal1()), &obj, SLOT(slot1()))
+ qmlobject_connect(&obj, MyObject, SIGNAL(signal1()), &obj, MyObject, SLOT(slot1()))
obj.signal1();
QCOMPARE(obj.slotCount, 1);
@@ -92,7 +92,7 @@ void tst_qqmlcpputils::fastConnect()
{
MyObject *obj = new MyObject;
QSignalSpy spy(obj, SIGNAL(signal2()));
- FAST_CONNECT(obj, SIGNAL(signal1()), obj, SIGNAL(signal2()));
+ qmlobject_connect(obj, MyObject, SIGNAL(signal1()), obj, MyObject, SIGNAL(signal2()));
obj->signal1();
QCOMPARE(spy.count(), 1);
diff --git a/tests/auto/qml/qqmlecmascript/data/secondAlias.qml b/tests/auto/qml/qqmlecmascript/data/secondAlias.qml
new file mode 100644
index 0000000000..d818be34b2
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/secondAlias.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.0
+
+QtObject {
+ id: root
+
+ property int prop1: 100
+ property int prop2: 100
+
+ property alias alias1: root.prop1
+ property alias alias2: root.prop2
+
+ property int test: root.alias2
+
+ Component.onCompleted: root.prop2 = 200
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/varAlias.qml b/tests/auto/qml/qqmlecmascript/data/varAlias.qml
new file mode 100644
index 0000000000..4d1aee2e6d
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/varAlias.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+
+QtObject {
+ id: root
+
+ property int test: root.aliasProperty.value
+ property alias aliasProperty: root.varProperty
+ property var varProperty: new Object({ value: 192 });
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 30adb33739..f907a1cb21 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -266,6 +266,8 @@ private slots:
void signalEmitted();
void threadSignal();
void qqmldataDestroyed();
+ void secondAlias();
+ void varAlias();
private:
static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -6852,6 +6854,25 @@ void tst_qqmlecmascript::qqmldataDestroyed()
}
}
+void tst_qqmlecmascript::secondAlias()
+{
+ QQmlComponent c(&engine, testFileUrl("secondAlias.qml"));
+ QObject *object = c.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("test").toInt(), 200);
+ delete object;
+}
+
+// An alias to a var property works
+void tst_qqmlecmascript::varAlias()
+{
+ QQmlComponent c(&engine, testFileUrl("varAlias.qml"));
+ QObject *object = c.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("test").toInt(), 192);
+ delete object;
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"
diff --git a/tests/auto/qml/qqmlglobal/qqmlglobal.pro b/tests/auto/qml/qqmlglobal/qqmlglobal.pro
index b39c04500c..42ce3b5297 100644
--- a/tests/auto/qml/qqmlglobal/qqmlglobal.pro
+++ b/tests/auto/qml/qqmlglobal/qqmlglobal.pro
@@ -4,4 +4,4 @@ SOURCES += tst_qqmlglobal.cpp
macx:CONFIG -= app_bundle
CONFIG += parallel_test
-QT += qml-private testlib
+QT += qml-private testlib v8-private core-private
diff --git a/tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp b/tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp
index 5fe15a64fe..b4c83b35aa 100644
--- a/tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp
+++ b/tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp
@@ -119,7 +119,6 @@ void tst_qqmlinstruction::dump()
{
QQmlCompiledData::Instruction::StoreMetaObject i;
- i.data = 3;
i.aliasData = 6;
i.propertyCache = 7;
@@ -512,7 +511,7 @@ void tst_qqmlinstruction::dump()
<< "2\t\tSETID\t\t\t0\t\t\t\"testId\""
<< "3\t\tSET_DEFAULT"
<< "4\t\tCREATE_COMPONENT\t3"
- << "5\t\tSTORE_META\t\t3"
+ << "5\t\tSTORE_META\t\t"
<< "6\t\tSTORE_FLOAT\t\t3\t11.3"
<< "7\t\tSTORE_DOUBLE\t\t4\t14.8"
<< "8\t\tSTORE_INTEGER\t\t5\t9"
diff --git a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
index bcb8ee8963..b4e77dd266 100644
--- a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
+++ b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
@@ -537,7 +537,7 @@ void tst_qqmllistreference::engineTypes()
QVERIFY(o);
QQmlProperty p1(o, QLatin1String("myList"));
- QVERIFY(p1.propertyTypeCategory() == QQmlProperty::Normal);
+ QVERIFY(p1.propertyTypeCategory() == QQmlProperty::List);
QQmlProperty p2(o, QLatin1String("myList"), engine.rootContext());
QVERIFY(p2.propertyTypeCategory() == QQmlProperty::List);
diff --git a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
index 8e35c24b7d..d4f4fc0500 100644
--- a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
+++ b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
@@ -388,7 +388,6 @@ void tst_QQmlMetaObject::method()
for (int i = 0; i < parameterTypes.size(); ++i)
QCOMPARE(method.parameterType(i), parameterTypes.at(i));
QCOMPARE(method.parameterTypes(), parameterTypeNames);
- QCOMPARE(method.parameterNames(), parameterNames);
QCOMPARE(method.tag(), "");
QCOMPARE(QString::fromUtf8(method.typeName()), returnTypeName);
diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index 12a8325f97..248cc0d803 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -1854,7 +1854,7 @@ void tst_qqmlproperty::warnOnInvalidBinding()
QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
// V8 error message for invalid binding to anchor
- expectedWarning = testUrl.toString() + QString::fromLatin1(":14: Unable to assign QQuickItem_QML_7 to QQuickAnchorLine");
+ expectedWarning = testUrl.toString() + QString::fromLatin1(":14: Unable to assign QQuickItem_QML_6 to QQuickAnchorLine");
QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
QQmlComponent component(&engine, testUrl);
diff --git a/tests/auto/qmltest/buttonclick/tst_buttonclick.qml b/tests/auto/qmltest/buttonclick/tst_buttonclick.qml
index 840a7fd927..1474ee7186 100644
--- a/tests/auto/qmltest/buttonclick/tst_buttonclick.qml
+++ b/tests/auto/qmltest/buttonclick/tst_buttonclick.qml
@@ -57,9 +57,11 @@ Button {
when: windowShown
function test_click() {
+
compare(spy.count, 0)
button.clicked(1, 2);
compare(button.text, "Clicked");
+
compare(spy.count, 1)
compare(spy.signalArguments.length, 1)
compare(spy.signalArguments[0][0], 1)