aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)